aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2017-12-17 23:05:24 +0100
committerJ08nY2017-12-17 23:05:24 +0100
commit8b1578b3d9012bfaa936c4e0d8cce3ac341fecd7 (patch)
tree172c60b0cd9190ff539e57e2d506598663bc604d
parent06ad7b6b91ed2e0ff1ed64f5872341d1b87f4d0e (diff)
parent878bd3fb19c5f876c6852ca5274186850b3c189f (diff)
downloadecgen-8b1578b3d9012bfaa936c4e0d8cce3ac341fecd7.tar.gz
ecgen-8b1578b3d9012bfaa936c4e0d8cce3ac341fecd7.tar.zst
ecgen-8b1578b3d9012bfaa936c4e0d8cce3ac341fecd7.zip
-rw-r--r--.travis.yml7
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/exhaustive/ansi.c27
-rw-r--r--src/exhaustive/brainpool.c268
-rw-r--r--src/exhaustive/brainpool.h105
-rw-r--r--src/exhaustive/brainpool_rfc.c97
-rw-r--r--src/exhaustive/brainpool_rfc.h47
-rw-r--r--src/exhaustive/exhaustive.c118
-rw-r--r--src/gen/gens.c24
-rw-r--r--src/gen/gens.h13
-rw-r--r--src/gen/order.c8
-rw-r--r--src/gen/seed.c8
-rw-r--r--src/io/cli.c105
-rw-r--r--src/misc/types.h6
-rw-r--r--src/util/bits.c51
-rw-r--r--src/util/bits.h6
-rw-r--r--src/util/str.c16
-rw-r--r--src/util/str.h7
-rw-r--r--test/src/exhaustive/test_ansi.c50
-rw-r--r--test/src/exhaustive/test_brainpool.c98
-rw-r--r--test/src/exhaustive/test_brainpool_rfc.c229
-rw-r--r--test/src/gen/test_field.c2
-rw-r--r--test/src/gen/test_point.c4
-rw-r--r--test/src/test/default.c2
-rw-r--r--test/src/util/test_bits.c42
25 files changed, 1208 insertions, 134 deletions
diff --git a/.travis.yml b/.travis.yml
index 55210a0..7df44e2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,7 +24,12 @@ before_install:
- wget mirrors.kernel.org/ubuntu/pool/universe/p/pari/libpari-dev_2.9.3-1_amd64.deb
- wget mirrors.kernel.org/ubuntu/pool/universe/p/pari/pari-gp_2.9.3-1_amd64.deb
- wget mirrors.kernel.org/ubuntu/pool/main/r/readline/libreadline7_7.0-0ubuntu2_amd64.deb
- - sudo dpkg --force-all -i libreadline7_7.0-0ubuntu2_amd64.deb libpari-gmp-tls5_2.9.3-1_amd64.deb libpari-dev_2.9.3-1_amd64.deb pari-gp_2.9.3-1_amd64.deb
+ - wget mirrors.kernel.org/ubuntu/pool/main/n/ncurses/libtinfo5_6.0%2B20160625-1ubuntu1_amd64.deb
+ - wget http://pari.math.u-bordeaux.fr/pub/pari/packages/seadata.tgz
+ - sudo dpkg --force-all -i libtinfo5_6.0+20160625-1ubuntu1_amd64.deb libreadline7_7.0-0ubuntu2_amd64.deb libpari-gmp-tls5_2.9.3-1_amd64.deb libpari-dev_2.9.3-1_amd64.deb pari-gp_2.9.3-1_amd64.deb
+ - DATADIR=$(echo "default(datadir)" | gp -q | cut -d\" -f2)
+ - echo $DATADIR
+ - sudo tar --strip-components=1 -C ${DATADIR} -xzvf seadata.tgz data/
script: # Test, clean, build for release
- TEST=1 make unittest
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ebb028..fbaa39c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ file(GLOB SRC "src/math/*.c" "src/gen/*.c" "src/cm/*.c" "src/invalid/*.c" "src/i
set(ECGEN_SRC "src/ecgen.c" ${SRC})
set(ECONVERT_SRC "src/econvert.c")
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG -g -Wall -Werror -pedantic")
+set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG -g -Wall -Werror")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG -O3 -Wall")
include_directories(src)
diff --git a/src/exhaustive/ansi.c b/src/exhaustive/ansi.c
index 762ffb7..d870d76 100644
--- a/src/exhaustive/ansi.c
+++ b/src/exhaustive/ansi.c
@@ -9,6 +9,7 @@
#include "io/output.h"
#include "util/bits.h"
#include "util/memory.h"
+#include "util/str.h"
static seed_t *ansi_new() {
seed_t *result = seed_new();
@@ -17,26 +18,8 @@ static seed_t *ansi_new() {
}
bool ansi_seed_valid(const char *hex_str) {
- size_t len = strlen(hex_str);
- if (len < 40) {
- return false;
- }
- const char *str_start = hex_str;
- if (hex_str[0] == '0' && (hex_str[1] == 'x' || hex_str[1] == 'X')) {
- str_start = hex_str + 2;
- }
- while (*str_start != 0) {
- char c = *str_start++;
- if (!isxdigit(c)) return false;
- }
- return true;
-}
-
-static bits_t *seed_stoi(const char *cstr) {
- const char *seed_str = cstr;
- const char *prefix = strstr(cstr, "0x");
- if (prefix != NULL) seed_str = prefix + 2;
- return bits_from_hex(seed_str);
+ const char *seed = str_is_hex(hex_str);
+ return seed && strlen(seed) >= 40;
}
static void seed_hash(seed_t *seed) {
@@ -64,7 +47,7 @@ GENERATOR(ansi_gen_seed_random) {
GENERATOR(ansi_gen_seed_argument) {
seed_t *seed = ansi_new();
- seed->seed = seed_stoi(cfg->seed);
+ seed->seed = bits_from_hex(str_is_hex(cfg->seed));
seed_hash(seed);
seed_tsh(seed);
curve->seed = seed;
@@ -83,7 +66,7 @@ GENERATOR(ansi_gen_seed_input) {
}
seed_t *seed = ansi_new();
- seed->seed = seed_stoi(cstr);
+ seed->seed = bits_from_hex(str_is_hex(cstr));
seed_hash(seed);
seed_tsh(seed);
curve->seed = seed;
diff --git a/src/exhaustive/brainpool.c b/src/exhaustive/brainpool.c
new file mode 100644
index 0000000..fdabd6f
--- /dev/null
+++ b/src/exhaustive/brainpool.c
@@ -0,0 +1,268 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#include "brainpool.h"
+#include "gen/gens.h"
+#include "gen/point.h"
+#include "gen/seed.h"
+#include "io/output.h"
+#include "util/bits.h"
+#include "util/str.h"
+
+static seed_t *brainpool_new() {
+ seed_t *result = seed_new();
+ result->type = SEED_BRAINPOOL;
+ return result;
+}
+
+static void seed_wv(seed_t *seed) {
+ pari_sp ltop = avma;
+ GEN L = utoi(cfg->bits);
+ seed->brainpool.v = itou(gfloor(gdivgs(subis(L, 1), 160)));
+ seed->brainpool.w = itou(subis(subis(L, 160 * seed->brainpool.v), 1));
+ avma = ltop;
+}
+
+void brainpool_update_seed(bits_t *s) {
+ pari_sp ltop = avma;
+ GEN z = bits_to_i(s);
+ GEN t = Fp_add(z, gen_1, int2n(160));
+ bits_t *result = bits_from_i_len(t, 160);
+ avma = ltop;
+ bits_cpy(s, result);
+ bits_free(&result);
+}
+
+bits_t *brainpool_hash(const bits_t *s, long w, long v) {
+ pari_sp ltop = avma;
+ unsigned char h[20];
+ bits_sha1(s, h);
+ unsigned char hashout[20 * v];
+
+ GEN z = bits_to_i(s);
+ GEN m = int2n(160);
+ for (long i = 1; i <= v; ++i) {
+ bits_t *si = bits_from_i_len(Fp_add(z, stoi(i), m), 160);
+ bits_sha1(si, hashout + (20 * (i - 1)));
+ bits_free(&si);
+ }
+ bits_t *result = bits_from_raw(h, 20 * 8);
+ bits_shortenz(result, 20 * 8 - w);
+ bits_t *rest = bits_from_raw(hashout, (size_t)(20 * v * 8));
+ bits_concatz(result, rest, NULL);
+ bits_free(&rest);
+ avma = ltop;
+ return result;
+}
+
+bool brainpool_seed_valid(const char *hex_str) {
+ const char *seed = str_is_hex(hex_str);
+ return seed && strlen(seed) == 40;
+}
+
+GENERATOR(brainpool_gen_seed_random) {
+ seed_t *seed = brainpool_new();
+ seed->seed = bits_new_rand(160);
+ seed_wv(seed);
+ curve->seed = seed;
+ return 1;
+}
+
+GENERATOR(brainpool_gen_seed_argument) {
+ seed_t *seed = brainpool_new();
+ seed->seed = bits_from_hex(str_is_hex(cfg->seed));
+ seed_wv(seed);
+ curve->seed = seed;
+ return 1;
+}
+
+GENERATOR(brainpool_gen_seed_input) {
+ pari_sp ltop = avma;
+
+ GEN str = input_string("seed:");
+ const char *cstr = GSTR(str);
+ if (!brainpool_seed_valid(cstr)) {
+ fprintf(err, "SEED must be exactly 160 bits(40 hex characters).\n");
+ avma = ltop;
+ return 0;
+ }
+
+ seed_t *seed = brainpool_new();
+ seed->seed = bits_from_hex(str_is_hex(cstr));
+ seed_wv(seed);
+ curve->seed = seed;
+ return 1;
+}
+
+GENERATOR(brainpool_gen_field) {
+ pari_sp btop = avma;
+ seed_t *seed = curve->seed;
+ do {
+ if (seed->brainpool.update_seed) {
+ brainpool_update_seed(seed->seed);
+ seed->brainpool.update_seed = false;
+ }
+ bits_t *p_bits = brainpool_hash(seed->seed, seed->brainpool.w + 1,
+ seed->brainpool.v);
+ GEN c = bits_to_i(p_bits);
+ bits_free(&p_bits);
+ GEN p = c;
+ pari_sp bbtop = avma;
+ do {
+ if (p != c) {//yes, check ptr identity here
+ avma = bbtop;
+ }
+ p = nextprime(addii(p, gen_1));
+ } while (mod4(p) != 3);
+
+ GEN lower_bound = subii(int2u(cfg->bits - 1), gen_1);
+ GEN upper_bound = int2u(cfg->bits);
+ if (mpcmp(p, lower_bound) <= 0 || mpcmp(p, upper_bound) >= 0) {
+ brainpool_update_seed(seed->seed);
+ avma = btop;
+ continue;
+ }
+
+ if (!isprime(p)) {
+ brainpool_update_seed(seed->seed);
+ avma = btop;
+ continue;
+ }
+
+ curve->field = gcopy(p);
+ gerepileall(btop, 1, &curve->field);
+ break;
+ } while (true);
+
+ seed->brainpool.update_seed = true;
+ return 1;
+}
+
+GENERATOR(brainpool_gen_equation) {
+ // field is definitely prime
+ pari_sp btop = avma;
+ seed_t *seed = curve->seed;
+ do {
+ if (seed->brainpool.update_seed) {
+ brainpool_update_seed(seed->seed);
+ seed->brainpool.update_seed = false;
+ }
+
+ bits_t *a_bits =
+ brainpool_hash(seed->seed, seed->brainpool.w, seed->brainpool.v);
+ GEN a = bits_to_i(a_bits);
+ bits_free(&a_bits);
+ GEN am = Fp_invsafe(a, curve->field);
+ if (am == NULL) {
+ brainpool_update_seed(seed->seed);
+ avma = btop;
+ continue;
+ }
+
+ GEN z;
+ z = Fp_sqrtn(Fp_muls(am, -3, curve->field), stoi(4), curve->field,
+ NULL);
+ if (z == NULL) {
+ brainpool_update_seed(seed->seed);
+ avma = btop;
+ continue;
+ }
+ seed->brainpool.seed_a = bits_copy(seed->seed);
+
+ brainpool_update_seed(seed->seed);
+
+ bits_t *b_bits =
+ brainpool_hash(seed->seed, seed->brainpool.w, seed->brainpool.v);
+ GEN b = bits_to_i(b_bits);
+ bits_free(&b_bits);
+ if (!Fp_issquare(b, curve->field)) {
+ brainpool_update_seed(seed->seed);
+ bits_free(&seed->brainpool.seed_a);
+ avma = btop;
+ continue;
+ }
+ seed->brainpool.seed_b = bits_copy(seed->seed);
+
+ GEN mod_a = gmodulo(a, curve->field);
+ GEN mod_b = gmodulo(b, curve->field);
+
+ if (gequal0(gmulsg(-16, gadd(gmulsg(4, gpowgs(mod_a, 3)),
+ gmulsg(27, gsqr(mod_b)))))) {
+ brainpool_update_seed(seed->seed);
+ bits_free(&seed->brainpool.seed_a);
+ bits_free(&seed->brainpool.seed_b);
+ avma = btop;
+ continue;
+ }
+
+ curve->a = mod_a;
+ curve->b = mod_b;
+ gerepileall(btop, 2, &curve->a, &curve->b);
+ break;
+ } while (true);
+
+ seed->brainpool.update_seed = true;
+ return 1;
+}
+
+GENERATOR(brainpool_gen_gens) {
+ pari_sp ltop = avma;
+ seed_t *seed = curve->seed;
+ brainpool_update_seed(seed->seed);
+
+ bits_t *k_bits =
+ brainpool_hash(seed->seed, seed->brainpool.w, seed->brainpool.v);
+ GEN k = bits_to_i(k_bits);
+ bits_free(&k_bits);
+ GEN x = gen_0;
+ GEN Qy = ellordinate(curve->curve, x, 0);
+ while (glength(Qy) == 0) {
+ mpaddz(x, gen_1, x);
+ Qy = ellordinate(curve->curve, x, 0);
+ }
+
+ GEN P = NULL;
+ if (glength(Qy) == 1) {
+ P = mkvec2(x, gel(Qy, 1));
+ } else if (glength(Qy) == 2) {
+ if (random_bits(1)) {
+ P = mkvec2(x, gel(Qy, 1));
+ } else {
+ P = mkvec2(x, gel(Qy, 2));
+ }
+ } else {
+ avma = ltop;
+ return INT_MIN;
+ }
+
+ curve->generators = points_new(1);
+ point_t *G = point_new();
+ curve->generators[0] = G;
+ G->point = gerepilecopy(ltop, ellmul(curve->curve, P, k));
+ G->order = ellorder(curve->curve, G->point, NULL);
+ G->cofactor = divii(curve->order, G->order);
+
+ return 1;
+}
+
+CHECK(brainpool_check_gens) {
+ pari_sp ltop = avma;
+ point_t *G = curve->generators[0];
+ GEN min_degree = divis(subii(G->order, gen_1), 100);
+ if (mpcmp(min_degree, gens_get_embedding(curve->field, G->order)) >= 0) {
+ avma = ltop;
+ return -5;
+ }
+ avma = ltop;
+ return 1;
+}
+
+CHECK(brainpool_check_order) {
+ if (mpcmp(curve->order, curve->field) < 0) {
+ return 1;
+ } else {
+ return -4;
+ }
+} \ No newline at end of file
diff --git a/src/exhaustive/brainpool.h b/src/exhaustive/brainpool.h
new file mode 100644
index 0000000..0b19fa3
--- /dev/null
+++ b/src/exhaustive/brainpool.h
@@ -0,0 +1,105 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#ifndef ECGEN_BRAINPOOL_H
+#define ECGEN_BRAINPOOL_H
+
+#include "misc/types.h"
+
+/**
+ *
+ * @param s
+ */
+void brainpool_update_seed(bits_t *s);
+
+/**
+ *
+ * @param s
+ * @param w
+ * @param v
+ * @return
+ */
+bits_t *brainpool_hash(const bits_t *s, long w, long v);
+
+/**
+ * @brief
+ * @param hex_str
+ * @return
+ */
+bool brainpool_seed_valid(const char *hex_str);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_gen_seed_random);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_gen_seed_argument);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_gen_seed_input);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_gen_field);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_gen_equation);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_gen_gens);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+CHECK(brainpool_check_gens);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+CHECK(brainpool_check_order);
+
+#endif // ECGEN_BRAINPOOL_H
diff --git a/src/exhaustive/brainpool_rfc.c b/src/exhaustive/brainpool_rfc.c
new file mode 100644
index 0000000..81529d2
--- /dev/null
+++ b/src/exhaustive/brainpool_rfc.c
@@ -0,0 +1,97 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#include "brainpool_rfc.h"
+#include "brainpool.h"
+#include "util/bits.h"
+
+#define brainpool_delegate(func) \
+ int ret = func(curve, args, state); \
+ if (ret != 1) { \
+ return ret; \
+ } \
+ curve->seed->type = SEED_BRAINPOOL_RFC; \
+ return 1;
+
+GENERATOR(brainpool_rfc_gen_seed_argument) {
+ brainpool_delegate(brainpool_gen_seed_argument);
+}
+
+GENERATOR(brainpool_rfc_gen_seed_random) {
+ brainpool_delegate(brainpool_gen_seed_random);
+}
+
+GENERATOR(brainpool_rfc_gen_seed_input) {
+ brainpool_delegate(brainpool_gen_seed_input);
+}
+
+#undef brainpool_delegate
+
+GENERATOR(brainpool_rfc_gen_equation) {
+ // field is definitely prime
+ pari_sp btop = avma;
+ seed_t *seed = curve->seed;
+ do {
+ if (seed->brainpool.update_seed) {
+ brainpool_update_seed(seed->seed);
+ seed->brainpool.update_seed = false;
+ }
+
+ bits_t *a_bits =
+ brainpool_hash(seed->seed, seed->brainpool.w, seed->brainpool.v);
+ GEN a = bits_to_i(a_bits);
+ bits_free(&a_bits);
+ GEN am = Fp_invsafe(a, curve->field);
+ if (am == NULL) {
+ brainpool_update_seed(seed->seed);
+ avma = btop;
+ continue;
+ }
+ GEN z;
+ z = Fp_sqrtn(Fp_muls(am, -3, curve->field), stoi(4), curve->field,
+ NULL);
+ if (z == NULL) {
+ brainpool_update_seed(seed->seed);
+ avma = btop;
+ continue;
+ }
+ seed->brainpool.seed_a = bits_copy(seed->seed);
+
+ GEN b = NULL;
+ pari_sp bbtop = avma;
+ do {
+ if (b != NULL) {
+ avma = bbtop;
+ }
+ brainpool_update_seed(seed->seed);
+ bits_t *b_bits = brainpool_hash(seed->seed, seed->brainpool.w,
+ seed->brainpool.v);
+ b = bits_to_i(b_bits);
+ bits_free(&b_bits);
+ } while (Fp_issquare(b, curve->field));
+
+ seed->brainpool.seed_b = bits_copy(seed->seed);
+
+ GEN mod_a = gmodulo(a, curve->field);
+ GEN mod_b = gmodulo(b, curve->field);
+
+ if (gequal0(gmulsg(-16, gadd(gmulsg(4, gpowgs(mod_a, 3)),
+ gmulsg(27, gsqr(mod_b)))))) {
+ brainpool_update_seed(seed->seed);
+ bits_free(&seed->brainpool.seed_a);
+ bits_free(&seed->brainpool.seed_b);
+ avma = btop;
+ continue;
+ }
+
+ curve->a = mod_a;
+ curve->b = mod_b;
+ gerepileall(btop, 2, &curve->a, &curve->b);
+ break;
+ } while (true);
+
+ seed->brainpool.update_seed = true;
+ return 1;
+}
diff --git a/src/exhaustive/brainpool_rfc.h b/src/exhaustive/brainpool_rfc.h
new file mode 100644
index 0000000..8a27410
--- /dev/null
+++ b/src/exhaustive/brainpool_rfc.h
@@ -0,0 +1,47 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#ifndef ECGEN_BRAINPOOL_RFC_H
+#define ECGEN_BRAINPOOL_RFC_H
+
+#include "misc/types.h"
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_rfc_gen_seed_argument);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_rfc_gen_seed_random);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_rfc_gen_seed_input);
+
+/**
+ * @brief
+ * @param curve
+ * @param args
+ * @param state
+ * @return
+ */
+GENERATOR(brainpool_rfc_gen_equation);
+
+#endif // ECGEN_BRAINPOOL_RFC_H
diff --git a/src/exhaustive/exhaustive.c b/src/exhaustive/exhaustive.c
index ea1dc63..c5e9ffc 100644
--- a/src/exhaustive/exhaustive.c
+++ b/src/exhaustive/exhaustive.c
@@ -5,6 +5,8 @@
#include "exhaustive.h"
#include "anomalous.h"
#include "ansi.h"
+#include "brainpool.h"
+#include "brainpool_rfc.h"
#include "check.h"
#include "gen/curve.h"
#include "gen/equation.h"
@@ -38,6 +40,20 @@ void exhaustive_clear(exhaustive_t *setup) {
static void exhaustive_ginit(gen_f *generators) {
if (cfg->seed_algo) {
+ if (cfg->prime) {
+ generators[OFFSET_ORDER] = &order_gen_prime;
+ } else if (cfg->cofactor) {
+ generators[OFFSET_ORDER] = &order_gen_smallfact;
+ } else {
+ generators[OFFSET_ORDER] = &order_gen_any;
+ }
+
+ if (cfg->unique) {
+ generators[OFFSET_GENERATORS] = &gens_gen_one;
+ } else {
+ generators[OFFSET_GENERATORS] = &gens_gen_any;
+ }
+
switch (cfg->seed_algo) {
case SEED_ANSI: {
// setup ANSI X9.62 generators
@@ -50,25 +66,52 @@ static void exhaustive_ginit(gen_f *generators) {
generators[OFFSET_SEED] = &ansi_gen_seed_input;
}
}
+ if (cfg->random) {
+ generators[OFFSET_FIELD] = &field_gen_random;
+ } else {
+ generators[OFFSET_FIELD] = &field_gen_input;
+ }
generators[OFFSET_A] = &gen_skip;
generators[OFFSET_B] = &ansi_gen_equation;
- }
- case SEED_BRAINPOOL:
- break;
- case SEED_BRAINPOOL_RFC:
- break;
+ } break;
+ case SEED_BRAINPOOL: {
+ if (cfg->seed) {
+ generators[OFFSET_SEED] = &brainpool_gen_seed_argument;
+ } else {
+ if (cfg->random) {
+ generators[OFFSET_SEED] = &brainpool_gen_seed_random;
+ } else {
+ generators[OFFSET_SEED] = &brainpool_gen_seed_input;
+ }
+ }
+ generators[OFFSET_FIELD] = &brainpool_gen_field;
+ generators[OFFSET_A] = &gen_skip;
+ generators[OFFSET_B] = &brainpool_gen_equation;
+ generators[OFFSET_ORDER] = &order_gen_prime;
+ generators[OFFSET_GENERATORS] = &brainpool_gen_gens;
+ } break;
+ case SEED_BRAINPOOL_RFC: {
+ if (cfg->seed) {
+ generators[OFFSET_SEED] = &brainpool_rfc_gen_seed_argument;
+ } else {
+ if (cfg->random) {
+ generators[OFFSET_SEED] =
+ &brainpool_rfc_gen_seed_random;
+ } else {
+ generators[OFFSET_SEED] = &brainpool_rfc_gen_seed_input;
+ }
+ }
+ generators[OFFSET_FIELD] = &brainpool_gen_field;
+ generators[OFFSET_A] = &gen_skip;
+ generators[OFFSET_B] = &brainpool_rfc_gen_equation;
+ generators[OFFSET_ORDER] = &order_gen_prime;
+ generators[OFFSET_GENERATORS] = &brainpool_gen_gens;
+ } break;
case SEED_FIPS:
break;
default:
break;
}
- if (cfg->prime) {
- generators[OFFSET_ORDER] = &order_gen_prime;
- } else if (cfg->cofactor) {
- generators[OFFSET_ORDER] = &order_gen_smallfact;
- } else {
- generators[OFFSET_ORDER] = &order_gen_any;
- }
} else {
// setup normal generators
generators[OFFSET_SEED] = &gen_skip;
@@ -107,23 +150,23 @@ static void exhaustive_ginit(gen_f *generators) {
} else {
generators[OFFSET_ORDER] = &order_gen_any;
}
- }
- // setup common generators
- generators[OFFSET_CURVE] = &curve_gen_any;
- if (cfg->unique) {
- generators[OFFSET_GENERATORS] = &gens_gen_one;
- } else {
- generators[OFFSET_GENERATORS] = &gens_gen_any;
- }
+ if (cfg->method == METHOD_ANOMALOUS) {
+ generators[OFFSET_FIELD] = &anomalous_gen_field;
+ } else if (cfg->random) {
+ generators[OFFSET_FIELD] = &field_gen_random;
+ } else {
+ generators[OFFSET_FIELD] = &field_gen_input;
+ }
- if (cfg->method == METHOD_ANOMALOUS) {
- generators[OFFSET_FIELD] = &anomalous_gen_field;
- } else if (cfg->random) {
- generators[OFFSET_FIELD] = &field_gen_random;
- } else {
- generators[OFFSET_FIELD] = &field_gen_input;
+ if (cfg->unique) {
+ generators[OFFSET_GENERATORS] = &gens_gen_one;
+ } else {
+ generators[OFFSET_GENERATORS] = &gens_gen_any;
+ }
}
+ // setup common generators
+ generators[OFFSET_CURVE] = &curve_gen_any;
switch (cfg->points.type) {
case POINTS_RANDOM:
@@ -156,6 +199,25 @@ static void exhaustive_cinit(check_t **validators) {
check_t *hex_check = check_new(hex_check_param, NULL);
validators[OFFSET_POINTS] = hex_check;
}
+
+ if (cfg->method == METHOD_SEED) {
+ switch (cfg->seed_algo) {
+ case SEED_ANSI:
+ break;
+ case SEED_BRAINPOOL:
+ case SEED_BRAINPOOL_RFC: {
+ check_t *order_check = check_new(brainpool_check_order, NULL);
+ validators[OFFSET_ORDER] = order_check;
+ check_t *gens_check =
+ check_new(gens_check_anomalous, brainpool_check_gens, NULL);
+ validators[OFFSET_GENERATORS] = gens_check;
+ } break;
+ case SEED_FIPS:
+ break;
+ default:
+ break;
+ }
+ }
}
static void exhaustive_ainit(arg_t **gen_argss, arg_t **check_argss) {
@@ -172,12 +234,14 @@ static void exhaustive_ainit(arg_t **gen_argss, arg_t **check_argss) {
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;
}
+
if (cfg->cofactor) {
arg_t *order_arg = arg_new();
arg_t *gens_arg = arg_new();
@@ -245,6 +309,7 @@ int exhaustive_gen_retry(curve_t *curve, const exhaustive_t *setup,
}
timeout_stop();
if (diff > 0 && setup->validators && setup->validators[state]) {
+ pari_sp ctop = avma;
check_t *validator = setup->validators[state];
for (size_t i = 0; i < validator->nchecks; ++i) {
int new_diff =
@@ -254,6 +319,7 @@ int exhaustive_gen_retry(curve_t *curve, const exhaustive_t *setup,
break;
}
}
+ avma = ctop;
}
int new_state = state + diff;
diff --git a/src/gen/gens.c b/src/gen/gens.c
index 2cffbc4..04e7646 100644
--- a/src/gen/gens.c
+++ b/src/gen/gens.c
@@ -40,16 +40,27 @@ GENERATOR(gens_gen_one) {
CHECK(gens_check_anomalous) {
if (cfg->field == FIELD_BINARY) return 1;
- pari_sp ltop = avma;
for (size_t i = 0; i < curve->ngens; ++i) {
if (mpcmp(curve->field, curve->generators[i]->order) == 0) {
- avma = ltop;
return -5;
}
}
return 1;
}
+GEN gens_get_embedding(GEN prime, GEN order) {
+ pari_sp ltop = avma;
+ GEN degree = gen_0;
+ GEN power = gen_1;
+ GEN pm;
+ do {
+ degree = addii(degree, gen_1);
+ power = mulii(power, prime);
+ pm = subii(power, gen_1);
+ } while (!dvdii(pm, order));
+ return gerepilecopy(ltop, degree);
+}
+
CHECK(gens_check_embedding) {
HAS_ARG(args);
if (cfg->field == FIELD_BINARY) return 1;
@@ -59,13 +70,8 @@ CHECK(gens_check_embedding) {
GEN mind = strtoi(min_degree);
for (size_t i = 0; i < curve->ngens; ++i) {
- GEN power = gen_0;
- GEN pm;
- do {
- power = addii(power, gen_1);
- GEN ppow = powii(curve->field, power);
- pm = subii(ppow, gen_1);
- } while (!dvdii(pm, curve->generators[i]->order));
+ GEN power =
+ gens_get_embedding(curve->field, curve->generators[i]->order);
if (mpcmp(power, mind) <= 0) {
avma = ltop;
diff --git a/src/gen/gens.h b/src/gen/gens.h
index 18c9815..11b349b 100644
--- a/src/gen/gens.h
+++ b/src/gen/gens.h
@@ -30,6 +30,7 @@ GENERATOR(gens_gen_any);
GENERATOR(gens_gen_one);
/**
+ * CHECK(check_f)
*
* @param curve
* @param args
@@ -39,6 +40,18 @@ GENERATOR(gens_gen_one);
CHECK(gens_check_anomalous);
/**
+ * @brief Get the embedding degree of a subgroup of <code>order</code> in a
+ * power of F_prime.
+ *
+ * @param prime The order of the base field.
+ * @param order The order of the subgroup generator (in the curve group).
+ * @return The embedding degree 't' such that <code>order</code> divides
+ * 'prime^t - 1'.
+ */
+GEN gens_get_embedding(GEN prime, GEN order);
+
+/**
+ * CHECK(check_f)
*
* @param curve
* @param args
diff --git a/src/gen/order.c b/src/gen/order.c
index 366c2cd..1c9e280 100644
--- a/src/gen/order.c
+++ b/src/gen/order.c
@@ -20,10 +20,12 @@ GENERATOR(order_gen_input) {
}
GENERATOR(order_gen_any) {
+ pari_sp ltop = avma;
GEN ord = ellff_get_card(curve->curve);
if (isclone(ord)) {
- curve->order = gcopy(ord);
+ curve->order = gerepilecopy(ltop, ord);
} else {
+ avma = ltop;
curve->order = ord;
}
return 1;
@@ -36,7 +38,7 @@ GENERATOR(order_gen_sea) {
avma = ltop;
return -4;
} else {
- curve->order = order;
+ curve->order = gerepilecopy(ltop, order);
obj_insert_shallow(curve->curve, 1, order);
return 1;
}
@@ -86,7 +88,7 @@ GENERATOR(order_gen_prime) {
avma = ltop;
return -4;
} else {
- curve->order = order;
+ curve->order = gerepilecopy(ltop, order);
obj_insert_shallow(curve->curve, 1, curve->order);
return 1;
}
diff --git a/src/gen/seed.c b/src/gen/seed.c
index a13588e..ad56b18 100644
--- a/src/gen/seed.c
+++ b/src/gen/seed.c
@@ -4,6 +4,7 @@
*/
#include "seed.h"
+#include <misc/types.h>
#include "util/bits.h"
#include "util/memory.h"
@@ -35,9 +36,7 @@ seed_t *seed_new_clone(const seed_t *src) {
void seed_free(seed_t **seed) {
if (*seed) {
- if ((*seed)->seed) {
- bits_free(&(*seed)->seed);
- }
+ bits_free(&(*seed)->seed);
if ((*seed)->hash20) {
try_free((*seed)->hash20);
}
@@ -45,8 +44,9 @@ void seed_free(seed_t **seed) {
case SEED_ANSI:
break;
case SEED_BRAINPOOL:
- break;
case SEED_BRAINPOOL_RFC:
+ bits_free(&(*seed)->brainpool.seed_a);
+ bits_free(&(*seed)->brainpool.seed_b);
break;
case SEED_FIPS:
break;
diff --git a/src/io/cli.c b/src/io/cli.c
index 3c3dccd..702081b 100644
--- a/src/io/cli.c
+++ b/src/io/cli.c
@@ -6,6 +6,7 @@
#include <misc/config.h>
#include <string.h>
#include "exhaustive/ansi.h"
+#include "exhaustive/brainpool.h"
char cli_doc[] =
"ecgen, tool for generating Elliptic curve domain parameters.\v(C) 2017 "
@@ -19,6 +20,7 @@ enum opt_keys {
OPT_COFACTOR = 'k',
OPT_RANDOM = 'r',
OPT_ANSI = 's',
+ OPT_BRAINPOOL = 'b',
OPT_INVALID = 'i',
OPT_ORDER = 'n',
OPT_KOBLITZ = 'K',
@@ -38,47 +40,50 @@ enum opt_keys {
OPT_ANOMALOUS,
OPT_GPGEN,
OPT_GPCHECK,
- OPT_HEXCHECK
+ OPT_HEXCHECK,
+ OPT_BRAINPOOL_RFC
};
// clang-format off
struct argp_option cli_options[] = {
- {0, 0, 0, 0, "Field specification:", 1},
- {"fp", OPT_FP, 0, 0, "Prime field.", 1},
- {"f2m", OPT_F2M, 0, 0, "Binary field.", 1},
+ {0, 0, 0, 0, "Field specification:", 1},
+ {"fp", OPT_FP, 0, 0, "Prime field.", 1},
+ {"f2m", OPT_F2M, 0, 0, "Binary field.", 1},
- {0, 0, 0, 0, "Generation methods:", 2},
- {"order", OPT_ORDER, "ORDER", 0, "Generate a curve with given order (using Complex Multiplication). **NOT IMPLEMENTED**", 2},
- {"anomalous", OPT_ANOMALOUS, 0, 0, "Generate an anomalous curve (of trace one, with field order equal to curve order).", 2},
- {"ansi", OPT_ANSI, "SEED", OPTION_ARG_OPTIONAL, "Generate a curve from SEED (ANSI X9.62 verifiable procedure).", 2},
- {"invalid", OPT_INVALID, 0, 0, "Generate a set of invalid curves, for a given curve (using Invalid curve algorithm).", 2},
+ {0, 0, 0, 0, "Generation methods:", 2},
+ {"order", OPT_ORDER, "ORDER", 0, "Generate a curve with given order (using Complex Multiplication). **NOT IMPLEMENTED**", 2},
+ {"anomalous", OPT_ANOMALOUS, 0, 0, "Generate an anomalous curve (of trace one, with field order equal to curve order).", 2},
+ {"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},
+ {"invalid", OPT_INVALID, 0, 0, "Generate a set of invalid curves, for a given curve (using Invalid curve algorithm).", 2},
- {0, 0, 0, 0, "Generation options:", 3},
- {"random", OPT_RANDOM, 0, 0, "Generate a random curve (using Random approach).", 3},
- {"prime", OPT_PRIME, 0, 0, "Generate a curve with prime order.", 3},
- {"cofactor", OPT_COFACTOR, "BOUND", 0, "Generate a curve with cofactor up to BOUND.", 3},
- {"koblitz", OPT_KOBLITZ, "A", OPTION_ARG_OPTIONAL,"Generate a Koblitz curve (a in {0, 1}, b = 1).", 3},
- {"unique", OPT_UNIQUE, 0, 0, "Generate a curve with only one generator.", 3},
- {"gp-gen", OPT_GPGEN, "FUNC", 0, "Generate a curve param using a GP function. **NOT IMPLEMENTED**", 3},
- {"gp-check", OPT_GPCHECK, "FUNC", 0, "Check a generated curve param using a GP function. **NOT IMPLEMENTED**", 3},
- {"hex-check", OPT_HEXCHECK, "HEX", 0, "Check a generated curve param hex expansion for the HEX string.", 3},
- {"points", OPT_POINTS, "TYPE", 0, "Generate points of given type (random/prime/all/nonprime/none).", 3},
- {"count", OPT_COUNT, "COUNT", 0, "Generate multiple curves.", 3},
+ {0, 0, 0, 0, "Generation options:", 3},
+ {"random", OPT_RANDOM, 0, 0, "Generate a random curve (using Random approach).", 3},
+ {"prime", OPT_PRIME, 0, 0, "Generate a curve with prime order.", 3},
+ {"cofactor", OPT_COFACTOR, "BOUND", 0, "Generate a curve with cofactor up to BOUND.", 3},
+ {"koblitz", OPT_KOBLITZ, "A", OPTION_ARG_OPTIONAL, "Generate a Koblitz curve (a in {0, 1}, b = 1).", 3},
+ {"unique", OPT_UNIQUE, 0, 0, "Generate a curve with only one generator.", 3},
+ {"gp-gen", OPT_GPGEN, "FUNC", 0, "Generate a curve param using a GP function. **NOT IMPLEMENTED**", 3},
+ {"gp-check", OPT_GPCHECK, "FUNC", 0, "Check a generated curve param using a GP function. **NOT IMPLEMENTED**", 3},
+ {"hex-check", OPT_HEXCHECK, "HEX", 0, "Check a generated curve param hex expansion for the HEX string.", 3},
+ {"points", OPT_POINTS, "TYPE", 0, "Generate points of given type (random/prime/all/nonprime/none).", 3},
+ {"count", OPT_COUNT, "COUNT", 0, "Generate multiple curves.", 3},
- {0, 0, 0, 0, "Input/Output options:", 4},
- {"format", OPT_FORMAT, "FORMAT", 0, "Format to output in. One of {csv, json}, default is json.", 4},
- {"input", OPT_INPUT, "FILE", 0, "Input from file.", 4},
- {"output", OPT_OUTPUT, "FILE", 0, "Output into file. Overwrites any existing file!", 4},
- {"append", OPT_APPEND, 0, 0, "Append to output file (don't overwrite).", 4},
- {"verbose", OPT_VERBOSE, "FILE", OPTION_ARG_OPTIONAL, "Verbose logging (to stdout or file).", 4},
+ {0, 0, 0, 0, "Input/Output options:", 4},
+ {"format", OPT_FORMAT, "FORMAT", 0, "Format to output in. One of {csv, json}, default is json.", 4},
+ {"input", OPT_INPUT, "FILE", 0, "Input from file.", 4},
+ {"output", OPT_OUTPUT, "FILE", 0, "Output into file. Overwrites any existing file!", 4},
+ {"append", OPT_APPEND, 0, 0, "Append to output file (don't overwrite).", 4},
+ {"verbose", OPT_VERBOSE, "FILE", OPTION_ARG_OPTIONAL, "Verbose logging (to stdout or file).", 4},
- {0, 0, 0, 0, "Other:", 5},
- {"data-dir", OPT_DATADIR, "DIR", 0, "Set PARI/GP data directory (containing seadata package).", 5},
- {"memory", OPT_MEMORY, "SIZE", 0, "Use PARI stack of SIZE (can have suffix k/m/g).", 5},
- {"threads", OPT_THREADS, "NUM", 0, "Use NUM threads.", 5},
- {"thread-stack", OPT_TSTACK, "SIZE", 0, "Use PARI stack of SIZE (per thread, can have suffix k/m/g).", 5},
- {"timeout", OPT_TIMEOUT, "TIME", 0, "Timeout computation of a curve parameter after TIME (can have suffix s/m/h/d).", 5},
- {0}
+ {0, 0, 0, 0, "Other:", 5},
+ {"data-dir", OPT_DATADIR, "DIR", 0, "Set PARI/GP data directory (containing seadata package).", 5},
+ {"memory", OPT_MEMORY, "SIZE", 0, "Use PARI stack of SIZE (can have suffix k/m/g).", 5},
+ {"threads", OPT_THREADS, "NUM", 0, "Use NUM threads.", 5},
+ {"thread-stack", OPT_TSTACK, "SIZE", 0, "Use PARI stack of SIZE (per thread, can have suffix k/m/g).", 5},
+ {"timeout", OPT_TIMEOUT, "TIME", 0, "Timeout computation of a curve parameter after TIME (can have suffix s/m/h/d).", 5},
+ {0}
};
// clang-format on
@@ -130,13 +135,9 @@ static void cli_end(struct argp_state *state) {
// Only one gen method
switch (cfg->method) {
case METHOD_DEFAULT:
- break;
case METHOD_CM:
- break;
case METHOD_ANOMALOUS:
- break;
case METHOD_SEED:
- break;
case METHOD_INVALID:
break;
default:
@@ -146,6 +147,11 @@ static void cli_end(struct argp_state *state) {
break;
}
+ if (cfg->method == METHOD_SEED && cfg->seed_algo == SEED_BRAINPOOL &&
+ cfg->field == FIELD_BINARY) {
+ argp_failure(state, 1, 0,
+ "Brainpool algorithm only creates prime field curves.");
+ }
/*
// Invalid is not prime or seed by definition.
if (cfg->invalid &&
@@ -227,6 +233,30 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) {
cfg->seed = arg;
}
break;
+ case OPT_BRAINPOOL:
+ cfg->method |= METHOD_SEED;
+ cfg->seed_algo = SEED_BRAINPOOL;
+ if (arg) {
+ if (!brainpool_seed_valid(arg)) {
+ argp_failure(
+ state, 1, 0,
+ "SEED must be exactly 160 bits (40 hex characters).");
+ }
+ cfg->seed = arg;
+ }
+ break;
+ case OPT_BRAINPOOL_RFC:
+ cfg->method |= METHOD_SEED;
+ cfg->seed_algo = SEED_BRAINPOOL_RFC;
+ if (arg) {
+ if (!brainpool_seed_valid(arg)) {
+ argp_failure(
+ state, 1, 0,
+ "SEED must be exactly 160 bits (40 hex characters).");
+ }
+ cfg->seed = arg;
+ }
+ break;
/* Generation options */
case OPT_COUNT:
@@ -299,7 +329,6 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) {
}
break;
}
-
/* IO options */
case OPT_FORMAT:
if (!strcmp(arg, "csv")) {
diff --git a/src/misc/types.h b/src/misc/types.h
index aecf207..76f8510 100644
--- a/src/misc/types.h
+++ b/src/misc/types.h
@@ -44,7 +44,11 @@ typedef struct {
GEN r;
} ansi;
struct {
- bits_t *f;
+ bool update_seed;
+ long w;
+ long v;
+ bits_t *seed_a;
+ bits_t *seed_b;
} brainpool;
};
} seed_t;
diff --git a/src/util/bits.c b/src/util/bits.c
index e5f28c1..a0a3795 100644
--- a/src/util/bits.c
+++ b/src/util/bits.c
@@ -4,6 +4,7 @@
*/
#include "bits.h"
+#include <misc/types.h>
#include <sha1/sha1.h>
#include "util/memory.h"
@@ -16,6 +17,36 @@ bits_t *bits_new(size_t bit_len) {
return result;
}
+bits_t *bits_new_rand(size_t bit_len) {
+ bits_t *result = bits_new(bit_len);
+ for (size_t i = 0; i < result->allocated; ++i) {
+ if (i == result->allocated - 1) {
+ size_t last_bits = bit_len % 8;
+ result->bits[i] = (unsigned char)random_bits(last_bits)
+ << (8 - last_bits);
+ } else {
+ result->bits[i] = (unsigned char)random_bits(8);
+ }
+ }
+ return result;
+}
+
+void bits_cpy(bits_t *dest, const bits_t *src) {
+ if (src->bitlen == 0) {
+ return;
+ }
+
+ if (src->allocated < dest->allocated) {
+ memset(dest->bits + src->allocated, 0,
+ dest->allocated - src->allocated);
+ } else if (src->allocated > dest->allocated) {
+ dest->bits = try_realloc(dest->bits, src->allocated);
+ }
+ memcpy(dest->bits, src->bits, src->allocated);
+ dest->allocated = src->allocated;
+ dest->bitlen = src->bitlen;
+}
+
bits_t *bits_copy(const bits_t *bits) {
bits_t *result = try_calloc(sizeof(bits_t));
result->bitlen = bits->bitlen;
@@ -49,6 +80,24 @@ bits_t *bits_from_i(GEN i) {
return result;
}
+bits_t *bits_from_i_len(GEN i, size_t bit_len) {
+ pari_sp ltop = avma;
+ GEN bitvec = binary_zv(i);
+ size_t i_len = (size_t)glength(bitvec);
+ bits_t *result = bits_new(bit_len);
+ size_t offset = 0;
+ if (i_len < bit_len) {
+ offset = bit_len - i_len;
+ }
+ for (size_t j = 0; j < bit_len; ++j) {
+ if (j < i_len && gel(bitvec, j + 1) == (GEN)1) {
+ result->bits[(j + offset) / 8] |= 1 << (7 - ((j + offset) % 8));
+ }
+ }
+ avma = ltop;
+ return result;
+}
+
bits_t *bits_from_hex(const char *hex_str) {
size_t nibble_len = strlen(hex_str);
bits_t *result = bits_new(nibble_len * 4);
@@ -102,7 +151,7 @@ GEN bits_to_i(const bits_t *bits) {
if (GET_BIT(bits->bits, i) != 0)
result = addii(result, int2n(bits->bitlen - i - 1));
}
- return gerepileupto(ltop, result);
+ return gerepilecopy(ltop, result);
}
char *bits_to_hex(const bits_t *bits) {
diff --git a/src/util/bits.h b/src/util/bits.h
index 2766cc3..000d64f 100644
--- a/src/util/bits.h
+++ b/src/util/bits.h
@@ -29,12 +29,18 @@
bits_t *bits_new(size_t bit_len);
+bits_t *bits_new_rand(size_t bit_len);
+
+void bits_cpy(bits_t *dest, const bits_t *src);
+
bits_t *bits_copy(const bits_t *bits);
void bits_free(bits_t **bits);
bits_t *bits_from_i(GEN i);
+bits_t *bits_from_i_len(GEN i, size_t bitlen);
+
bits_t *bits_from_hex(const char *hex_str);
bits_t *bits_from_bin(const char *bin_str);
diff --git a/src/util/str.c b/src/util/str.c
index 933eb83..3f9f39c 100644
--- a/src/util/str.c
+++ b/src/util/str.c
@@ -3,9 +3,25 @@
* Copyright (C) 2017 J08nY
*/
#include "str.h"
+#include <ctype.h>
#include <string.h>
#include "util/memory.h"
+const char *str_is_hex(const char *hex_str) {
+ const char *str_start = hex_str;
+ if (strlen(hex_str) > 2) {
+ if (hex_str[0] == '0' && (hex_str[1] == 'x' || hex_str[1] == 'X')) {
+ str_start = hex_str + 2;
+ }
+ }
+ const char *s = str_start;
+ while (*s != 0) {
+ char c = *s++;
+ if (!isxdigit(c)) return NULL;
+ }
+ return str_start;
+}
+
char *str_join(char *strings[], size_t len) {
size_t total = 0;
for (size_t i = 0; i < len; ++i) {
diff --git a/src/util/str.h b/src/util/str.h
index 2e14272..9b5709e 100644
--- a/src/util/str.h
+++ b/src/util/str.h
@@ -12,6 +12,13 @@
/**
* @brief
+ * @param hex_str
+ * @return
+ */
+const char *str_is_hex(const char *hex_str);
+
+/**
+ * @brief
* @param strings
* @param len
* @return
diff --git a/test/src/exhaustive/test_ansi.c b/test/src/exhaustive/test_ansi.c
index f1177c7..4724336 100644
--- a/test/src/exhaustive/test_ansi.c
+++ b/test/src/exhaustive/test_ansi.c
@@ -16,8 +16,8 @@
TestSuite(ansi, .init = io_setup, .fini = io_teardown);
-Test(ansi, test_seed_random) {
- curve_t curve = {};
+Test(ansi, test_ansi_seed_random) {
+ curve_t curve = {0};
cfg->bits = 256;
int ret = ansi_gen_seed_random(&curve, NULL, OFFSET_SEED);
@@ -27,8 +27,8 @@ Test(ansi, test_seed_random) {
seed_free(&curve.seed);
}
-Test(ansi, test_seed_argument) {
- curve_t curve = {};
+Test(ansi, test_ansi_seed_argument) {
+ curve_t curve = {0};
char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
cfg->seed = seed;
cfg->bits = 256;
@@ -43,8 +43,8 @@ Test(ansi, test_seed_argument) {
seed_free(&curve.seed);
}
-Test(ansi, test_seed_argument_hex) {
- curve_t curve = {};
+Test(ansi, test_ansi_seed_argument_hex) {
+ curve_t curve = {0};
char *seed = "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd";
cfg->seed = seed;
cfg->bits = 256;
@@ -59,8 +59,8 @@ Test(ansi, test_seed_argument_hex) {
seed_free(&curve.seed);
}
-Test(ansi, test_seed_input) {
- curve_t curve = {};
+Test(ansi, test_ansi_seed_input) {
+ curve_t curve = {0};
char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
cfg->bits = 256;
fprintf(write_in, "%s\n", seed);
@@ -75,8 +75,8 @@ Test(ansi, test_seed_input) {
seed_free(&curve.seed);
}
-Test(ansi, test_seed_input_short) {
- curve_t curve = {};
+Test(ansi, test_ansi_seed_input_short) {
+ curve_t curve = {0};
char *seed = "abcdef";
fprintf(write_in, "%s\n", seed);
int ret = ansi_gen_seed_input(&curve, NULL, OFFSET_SEED);
@@ -102,8 +102,8 @@ void prime_params_cleanup(struct criterion_test_params *ctp) {
cr_free(params->b);
}
-ParameterizedTestParameters(ansi, test_seed_prime_examples) {
- static struct prime_params params[7] = {};
+ParameterizedTestParameters(ansi, test_ansi_seed_prime_examples) {
+ static struct prime_params params[7] = {{0}};
// Taken from ANSI X9.62 J.5.1 - J.5.3; p. 115 - 117
// clang-format off
params[0].bits = 192;
@@ -151,20 +151,22 @@ ParameterizedTestParameters(ansi, test_seed_prime_examples) {
// clang-format on
size_t nb_params = sizeof(params) / sizeof(struct prime_params);
- return cr_make_param_array(struct prime_params, params, nb_params, NULL);
+ return cr_make_param_array(struct prime_params, params, nb_params,
+ prime_params_cleanup);
}
-ParameterizedTest(struct prime_params *param, ansi, test_seed_prime_examples) {
+ParameterizedTest(struct prime_params *param, ansi,
+ test_ansi_seed_prime_examples) {
cfg->bits = param->bits;
cfg->field = FIELD_PRIME;
cfg->seed = param->seed;
- curve_t curve = {};
+ curve_t curve = {0};
bits_t *p = bits_from_hex(param->p);
curve.field = bits_to_i(p);
int ret = ansi_gen_seed_argument(&curve, NULL, OFFSET_SEED);
cr_assert_eq(ret, 1, );
- ret = ansi_gen_equation(&curve, NULL, OFFSET_SEED);
+ ret = ansi_gen_equation(&curve, NULL, OFFSET_B);
cr_assert_eq(ret, 1, );
GEN expected_r = bits_to_i(bits_from_hex(param->r));
cr_assert(gequal(curve.seed->ansi.r, expected_r), );
@@ -188,8 +190,8 @@ void binary_params_cleanup(struct criterion_test_params *ctp) {
cr_free(params->b);
}
-ParameterizedTestParameters(ansi, test_seed_binary_examples) {
- static struct binary_params params[10] = {};
+ParameterizedTestParameters(ansi, test_ansi_seed_binary_examples) {
+ static struct binary_params params[10] = {{0}};
// Taken from ANSI X9.62 J.4.1, J.4.3, J.4.5 and J.4.8; p. 107 - 113
// clang-format off
polynomial_t p163 = {163, 9, 3, 2};
@@ -253,24 +255,24 @@ ParameterizedTestParameters(ansi, test_seed_binary_examples) {
binary_params_cleanup);
}
ParameterizedTest(struct binary_params *param, ansi,
- test_seed_binary_examples) {
+ test_ansi_seed_binary_examples) {
cfg->bits = param->bits;
cfg->field = FIELD_BINARY;
cfg->seed = param->seed;
- curve_t curve = {};
+ curve_t curve = {0};
curve.field = poly_gen(&param->field);
- GEN expected_b = bits_to_i(bits_from_hex(param->b));
- bits_t *b = bits_from_i(expected_b);
+ bits_t *b_bits = bits_from_hex(param->b);
+ GEN expected_b = bits_to_i(b_bits);
+ bits_free(&b_bits);
int ret = ansi_gen_seed_argument(&curve, NULL, OFFSET_SEED);
cr_assert_eq(ret, 1, );
- ret = ansi_gen_equation(&curve, NULL, OFFSET_SEED);
+ ret = ansi_gen_equation(&curve, NULL, OFFSET_B);
cr_assert_eq(ret, 1, );
GEN curve_b = field_elementi(curve.b);
cr_assert(gequal(curve_b, expected_b), );
- bits_free(&b);
seed_free(&curve.seed);
} \ No newline at end of file
diff --git a/test/src/exhaustive/test_brainpool.c b/test/src/exhaustive/test_brainpool.c
new file mode 100644
index 0000000..80c11e3
--- /dev/null
+++ b/test/src/exhaustive/test_brainpool.c
@@ -0,0 +1,98 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#include <criterion/criterion.h>
+#include "exhaustive/brainpool.h"
+#include "gen/seed.h"
+#include "test/io.h"
+#include "util/bits.h"
+#include "util/memory.h"
+
+TestSuite(brainpool, .init = io_setup, .fini = io_teardown);
+
+Test(brainpool, test_brainpool_seed_random) {
+ curve_t curve = {0};
+ cfg->bits = 256;
+ int ret = brainpool_gen_seed_random(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.seed, );
+
+ seed_free(&curve.seed);
+}
+
+Test(brainpool, test_brainpool_seed_argument) {
+ curve_t curve = {0};
+ char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
+ cfg->seed = seed;
+ cfg->bits = 256;
+ int ret = brainpool_gen_seed_argument(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.seed, );
+ char *hex = bits_to_hex(curve.seed->seed);
+ cr_assert_str_eq(hex, seed, );
+
+ try_free(hex);
+ seed_free(&curve.seed);
+}
+
+Test(brainpool, test_brainpool_seed_input) {
+ curve_t curve = {0};
+ char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
+ cfg->bits = 256;
+ fprintf(write_in, "%s\n", seed);
+ int ret = brainpool_gen_seed_input(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.seed, );
+ char *hex = bits_to_hex(curve.seed->seed);
+ cr_assert_str_eq(hex, seed, );
+
+ try_free(hex);
+ seed_free(&curve.seed);
+}
+
+Test(brainpool, test_brainpool_seed_input_short) {
+ curve_t curve = {0};
+ char *seed = "abcdef";
+ fprintf(write_in, "%s\n", seed);
+ int ret = brainpool_gen_seed_input(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 0, );
+}
+
+Test(brainpool, test_brainpool_field) {
+ curve_t curve = {0};
+ char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
+ cfg->seed = seed;
+ cfg->bits = 256;
+
+ brainpool_gen_seed_argument(&curve, NULL, OFFSET_SEED);
+
+ int ret = brainpool_gen_field(&curve, NULL, OFFSET_FIELD);
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.field, );
+ cr_assert(isprime(gcopy(curve.field)), );
+ cr_assert_eq(mod4(curve.field), 3, );
+}
+
+Test(brainpool, test_brainpool_equation) {
+ curve_t curve = {0};
+ char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
+ cfg->seed = seed;
+ cfg->bits = 256;
+
+ brainpool_gen_seed_argument(&curve, NULL, OFFSET_SEED);
+
+ char *prime =
+ "caa002c44829499e8239f049bddcaca373258a175fa337a82e0521744392cff1";
+ bits_t *prime_bits = bits_from_hex(prime);
+ curve.field = bits_to_i(prime_bits);
+ bits_free(&prime_bits);
+
+ int ret = brainpool_gen_equation(&curve, NULL, OFFSET_B);
+ cr_assert_eq(ret, 1, );
+} \ No newline at end of file
diff --git a/test/src/exhaustive/test_brainpool_rfc.c b/test/src/exhaustive/test_brainpool_rfc.c
new file mode 100644
index 0000000..4fc710f
--- /dev/null
+++ b/test/src/exhaustive/test_brainpool_rfc.c
@@ -0,0 +1,229 @@
+/*
+ * ecgen, tool for generating Elliptic curve domain parameters
+ * Copyright (C) 2017 J08nY
+ */
+
+#include <criterion/criterion.h>
+#include <criterion/parameterized.h>
+#include "exhaustive/brainpool.h"
+#include "exhaustive/brainpool_rfc.h"
+#include "exhaustive/check.h"
+#include "exhaustive/exhaustive.h"
+#include "gen/curve.h"
+#include "gen/gens.h"
+#include "gen/order.h"
+#include "gen/seed.h"
+#include "misc/types.h"
+#include "test/io.h"
+#include "test/memory.h"
+#include "util/bits.h"
+#include "util/memory.h"
+
+TestSuite(brainpool_rfc, .init = io_setup, .fini = io_teardown);
+
+Test(brainpool_rfc, test_brainpool_rfc_seed_random) {
+ curve_t curve = {0};
+ cfg->bits = 256;
+ int ret = brainpool_rfc_gen_seed_random(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.seed, );
+
+ seed_free(&curve.seed);
+}
+
+Test(brainpool_rfc, test_brainpool_rfc_seed_argument) {
+ curve_t curve = {0};
+ char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
+ cfg->seed = seed;
+ cfg->bits = 256;
+ int ret = brainpool_rfc_gen_seed_argument(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.seed, );
+ char *hex = bits_to_hex(curve.seed->seed);
+ cr_assert_str_eq(hex, seed, );
+
+ try_free(hex);
+ seed_free(&curve.seed);
+}
+
+Test(brainpool_rfc, test_brainpool_rfc_seed_input) {
+ curve_t curve = {0};
+ char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
+ cfg->bits = 256;
+ fprintf(write_in, "%s\n", seed);
+ int ret = brainpool_rfc_gen_seed_input(&curve, NULL, OFFSET_SEED);
+
+ cr_assert_eq(ret, 1, );
+ cr_assert_not_null(curve.seed, );
+ char *hex = bits_to_hex(curve.seed->seed);
+ cr_assert_str_eq(hex, seed, );
+
+ try_free(hex);
+ seed_free(&curve.seed);
+}
+
+struct rfc_params {
+ size_t bits;
+ char *p_seed;
+ char *p;
+ char *ab_seed;
+ char *a;
+ char *b;
+};
+
+void params_cleanup(struct criterion_test_params *ctp) {
+ struct rfc_params *params = (struct rfc_params *)ctp->params;
+ cr_free(params->p_seed);
+ cr_free(params->p);
+ cr_free(params->ab_seed);
+ cr_free(params->a);
+ cr_free(params->b);
+}
+
+/**
+ * These fail because brainpool_rfc_gen_equation only implements the one curve
+ * generation step and
+ * does not do other Brainpool checks(which are a part of the procedure).*/
+ParameterizedTestParameters(brainpool_rfc, test_brainpool_rfc_params) {
+ static struct rfc_params params[7] = {{0}};
+
+ params[0].bits = 160;
+ params[0].p_seed = cr_strdup("3243F6A8885A308D313198A2E03707344A409382");
+ params[0].p = cr_strdup("E95E4A5F737059DC60DFC7AD95B3D8139515620F");
+ params[0].ab_seed = cr_strdup("2B7E151628AED2A6ABF7158809CF4F3C762E7160");
+ params[0].a = cr_strdup("340E7BE2A280EB74E2BE61BADA745D97E8F7C300");
+ params[0].b = cr_strdup("1E589A8595423412134FAA2DBDEC95C8D8675E58");
+ params[1].bits = 192;
+ params[1].p_seed = cr_strdup("2299F31D0082EFA98EC4E6C89452821E638D0137");
+ params[1].p = cr_strdup("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297");
+ params[1].ab_seed = cr_strdup("F38B4DA56A784D9045190CFEF324E7738926CFBE");
+ params[1].a = cr_strdup("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF");
+ params[1].b = cr_strdup("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9");
+ params[2].bits = 224;
+ params[2].p_seed = cr_strdup("7BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B");
+ params[2].p =
+ cr_strdup("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF");
+ params[2].ab_seed = cr_strdup("5F4BF8D8D8C31D763DA06C80ABB1185EB4F7C7B5");
+ params[2].a =
+ cr_strdup("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43");
+ params[2].b =
+ cr_strdup("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B");
+ params[3].bits = 256;
+ params[3].p_seed = cr_strdup("5B54709179216D5D98979FB1BD1310BA698DFB5A");
+ params[3].p = cr_strdup(
+ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377");
+ params[3].ab_seed = cr_strdup("757F5958490CFD47D7C19BB42158D9554F7B46BC");
+ params[3].a = cr_strdup(
+ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9");
+ params[3].b = cr_strdup(
+ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6");
+ params[4].bits = 320;
+ params[4].p_seed = cr_strdup("C2FFD72DBD01ADFB7B8E1AFED6A267E96BA7C904");
+ params[4].p = cr_strdup(
+ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412"
+ "B1F1B32E27");
+ params[4].ab_seed = cr_strdup("ED55C4D79FD5F24D6613C31C3839A2DDF8A9A276");
+ params[4].a = cr_strdup(
+ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375"
+ "A97D860EB4");
+ params[4].b = cr_strdup(
+ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4"
+ "AC8FB1F1A6");
+ params[5].bits = 384;
+ params[5].p_seed = cr_strdup("5F12C7F9924A19947B3916CF70801F2E2858EFC1");
+ params[5].p = cr_strdup(
+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A7"
+ "29901D1A71874700133107EC53");
+ params[5].ab_seed = cr_strdup("BCFBFA1C877C56284DAB79CD4C2B3293D20E9E5E");
+ params[5].a = cr_strdup(
+ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA581"
+ "4A503AD4EB04A8C7DD22CE2826");
+ params[5].b = cr_strdup(
+ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB439"
+ "0295DBC9943AB78696FA504C11");
+ params[6].bits = 512;
+ params[6].p_seed = cr_strdup("6636920D871574E69A458FEA3F4933D7E0D95748");
+ params[6].p = cr_strdup(
+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B"
+ "009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3");
+ params[6].ab_seed = cr_strdup("AF02AC60ACC93ED874422A52ECB238FEEE5AB6AD");
+ params[6].a = cr_strdup(
+ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D"
+ "5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA");
+ params[6].b = cr_strdup(
+ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7"
+ "B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723");
+
+ size_t nb_params = sizeof(params) / sizeof(struct rfc_params);
+ return cr_make_param_array(struct rfc_params, params, nb_params,
+ params_cleanup);
+}
+ParameterizedTest(struct rfc_params *param, brainpool_rfc,
+ test_brainpool_rfc_params) {
+ cr_skip();
+ cfg->bits = param->bits;
+ cfg->field = FIELD_PRIME;
+
+ bits_t *p_bits = bits_from_hex(param->p);
+ bits_t *a_bits = bits_from_hex(param->a);
+ bits_t *b_bits = bits_from_hex(param->b);
+ GEN p = bits_to_i(p_bits);
+ GEN a = gmodulo(bits_to_i(a_bits), p);
+ GEN b = gmodulo(bits_to_i(b_bits), p);
+ bits_free(&p_bits);
+ bits_free(&a_bits);
+ bits_free(&b_bits);
+
+ curve_t curve = {0};
+ cfg->seed = param->p_seed;
+ int ret = brainpool_rfc_gen_seed_argument(&curve, NULL, OFFSET_SEED);
+ cr_assert_not_null(curve.seed, );
+ cr_assert_eq(ret, 1, );
+
+ ret = brainpool_gen_field(&curve, NULL, OFFSET_FIELD);
+ cr_assert_not_null(curve.field, );
+ cr_assert_eq(ret, 1, );
+ cr_assert(equalii(curve.field, p), );
+
+ seed_free(&curve.seed);
+ cfg->seed = param->ab_seed;
+ ret = brainpool_rfc_gen_seed_argument(&curve, NULL, OFFSET_SEED);
+ cr_assert_not_null(curve.seed, );
+ cr_assert_eq(ret, 1, );
+
+ exhaustive_t setup = {0};
+ gen_f gens[OFFSET_END] = {0};
+ gens[OFFSET_A] = &gen_skip;
+ gens[OFFSET_B] = &brainpool_rfc_gen_equation;
+ gens[OFFSET_CURVE] = &curve_gen_any;
+ gens[OFFSET_ORDER] = &order_gen_prime;
+ gens[OFFSET_GENERATORS] = &brainpool_gen_gens;
+ gens[OFFSET_POINTS] = &gen_skip;
+ check_t *checks[OFFSET_END] = {0};
+ checks[OFFSET_ORDER] = check_new(brainpool_check_order, NULL);
+ checks[OFFSET_GENERATORS] =
+ check_new(gens_check_anomalous, brainpool_check_gens, NULL);
+ unroll_f unrolls[OFFSET_END] = {0};
+ unrolls[OFFSET_CURVE] = &curve_unroll;
+ unrolls[OFFSET_GENERATORS] = &gens_unroll;
+ setup.generators = gens;
+ setup.validators = checks;
+ setup.unrolls = unrolls;
+
+ // pari_sp top = avma;
+ // pari_ulong debug_before = DEBUGLEVEL;
+ // DEBUGLEVEL = 3;
+ ret = exhaustive_gen(&curve, &setup, OFFSET_A, OFFSET_GENERATORS);
+ // DEBUGLEVEL = debug_before;
+ // dbg_gerepile(top);
+
+ cr_assert_not_null(curve.a, );
+ cr_assert_not_null(curve.b, );
+ cr_assert_eq(ret, 1, );
+ cr_assert(gequal(curve.a, a), );
+ cr_assert(gequal(curve.b, b), );
+
+ seed_free(&curve.seed);
+} \ No newline at end of file
diff --git a/test/src/gen/test_field.c b/test/src/gen/test_field.c
index 6ceeca4..03bd626 100644
--- a/test/src/gen/test_field.c
+++ b/test/src/gen/test_field.c
@@ -62,7 +62,7 @@ Test(field, test_field_gen_input_fp) {
ret = field_gen_input(&curve, NULL, OFFSET_FIELD);
cr_assert_eq(ret, 0, );
cr_assert_null(curve.field, );
-};
+}
Test(field, test_field_gen_input_f2m) {
curve_t curve = {0};
diff --git a/test/src/gen/test_point.c b/test/src/gen/test_point.c
index 86eede1..19869c5 100644
--- a/test/src/gen/test_point.c
+++ b/test/src/gen/test_point.c
@@ -5,9 +5,9 @@
#include <criterion/criterion.h>
#include "gen/point.h"
-#include "test/default.h"
+#include "test/io.h"
-TestSuite(point, .init = default_setup, .fini = default_teardown);
+TestSuite(point, .init = io_setup, .fini = io_teardown);
Test(point, test_point_random) {
// curve = ellinit([1, 3], 23), order = 27
diff --git a/test/src/test/default.c b/test/src/test/default.c
index 3587032..5a30e79 100644
--- a/test/src/test/default.c
+++ b/test/src/test/default.c
@@ -9,7 +9,7 @@
void default_setup(void) {
memset(cfg, 0, sizeof(config_t));
- pari_init(1000000, 1000000);
+ pari_init(200000000, 4000000); // 200MB memory, 4M primes
// set_mem_funcs(cr_malloc, cr_simple_calloc, cr_realloc, cr_free);
}
diff --git a/test/src/util/test_bits.c b/test/src/util/test_bits.c
index 70060c9..8a356b0 100644
--- a/test/src/util/test_bits.c
+++ b/test/src/util/test_bits.c
@@ -5,10 +5,12 @@
#include <criterion/criterion.h>
#include <criterion/parameterized.h>
+#include <misc/types.h>
#include "test/default.h"
#include "test/memory.h"
#include "util/bits.h"
#include "util/memory.h"
+#include "util/random.h"
TestSuite(bits, .init = default_setup, .fini = default_teardown);
@@ -22,6 +24,35 @@ Test(bits, test_bits_new) {
bits_free(&bits);
}
+Test(bits, test_bits_new_rand) {
+ random_init();
+ GEN seed = getrand();
+ bits_t *bits = bits_new_rand(10);
+ cr_assert_not_null(bits, );
+ cr_assert_eq(bits->bitlen, 10, );
+ cr_assert_eq(bits->allocated, 2, );
+
+ setrand(seed);
+ unsigned char one = (unsigned char)random_bits(8);
+ unsigned char other = (unsigned char)random_bits(2) << 6;
+ cr_assert_eq(bits->bits[0], one, );
+ cr_assert_eq(bits->bits[1], other, );
+ bits_free(&bits);
+}
+
+Test(bits, test_bits_cpy) {
+ bits_t *bits = bits_new(10);
+ bits->bits[0] = 0b10101010;
+ bits->bits[1] = 0b11000000;
+
+ bits_t *other = bits_new(5);
+ bits_cpy(other, bits);
+ cr_assert_eq(other->bitlen, bits->bitlen, );
+ cr_assert_eq(other->allocated, bits->allocated, );
+ cr_assert_eq(other->bits[0], bits->bits[0], );
+ cr_assert_eq(other->bits[1], bits->bits[1], );
+}
+
Test(bits, test_bits_copy) {
bits_t *bits = bits_new(10);
bits->bits[0] = 0b10101010;
@@ -48,6 +79,17 @@ Test(bits, test_bits_from_i) {
bits_free(&bits);
}
+Test(bits, test_bits_from_i_len) {
+ GEN i = int2n(5);
+
+ bits_t *bits = bits_from_i_len(i, 7);
+ cr_assert_not_null(bits, );
+ cr_assert_eq(bits->bitlen, 7, );
+ cr_assert_eq(bits->allocated, 1, );
+ cr_assert_eq(bits->bits[0], 0b01000000, );
+ bits_free(&bits);
+}
+
Test(bits, test_bits_from_hex) {
char *hex = "0ab";