diff options
| author | J08nY | 2017-09-19 13:07:45 +0200 |
|---|---|---|
| committer | J08nY | 2017-09-19 13:07:45 +0200 |
| commit | 0d068cefe5f43d69fb7bae0c7882598c1213f60b (patch) | |
| tree | 29bf69e2bf51e33617b78e4439c8b0077e543b1d | |
| parent | bfeeedd8b158288b1e66e241620966e933c9e3c7 (diff) | |
| parent | 8448edf40ea8d8b128ff83dc08335b3bf14718cb (diff) | |
| download | ecgen-0d068cefe5f43d69fb7bae0c7882598c1213f60b.tar.gz ecgen-0d068cefe5f43d69fb7bae0c7882598c1213f60b.tar.zst ecgen-0d068cefe5f43d69fb7bae0c7882598c1213f60b.zip | |
54 files changed, 1907 insertions, 323 deletions
diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..5fc845c --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,7 @@ +coverage: + range: 50..100 + round: up + precision: 2 + ignore: + - "**/test_*.c" + - "lib" diff --git a/CMakeLists.txt b/CMakeLists.txt index a13030d..6d7c624 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ include_directories(lib) find_library(parson parson/libparson.a) find_library(sha1 sha1/libsha1.a) -file(GLOB SRC "src/math/*.c" "src/gen/*.c" "src/cm/*.c" "src/invalid/*.c" "src/io/*.c" "src/exhaustive/*.c" "src/util/*.c") +file(GLOB SRC "src/math/*.c" "src/gen/*.c" "src/cm/*.c" "src/invalid/*.c" "src/io/*.c" "src/exhaustive/*.c" "src/misc/*.c" "src/util/*.c") set(ECGEN_SRC "src/ecgen.c" ${SRC}) set(ECONVERT_SRC "src/econvert.c") diff --git a/src/cm/cm.h b/src/cm/cm.h index 546c0d5..d59db87 100644 --- a/src/cm/cm.h +++ b/src/cm/cm.h @@ -9,7 +9,7 @@ #define ECGEN_CM_H #include "io/cli.h" -#include "io/config.h" +#include "misc/config.h" /** * diff --git a/src/exhaustive/anomalous.h b/src/exhaustive/anomalous.h index ff6c053..cf8c208 100644 --- a/src/exhaustive/anomalous.h +++ b/src/exhaustive/anomalous.h @@ -10,7 +10,7 @@ #include <pari/pari.h> #include "arg.h" -#include "gen/types.h" +#include "misc/types.h" #include "io/cli.h" typedef struct disc_t { diff --git a/src/exhaustive/ansi.c b/src/exhaustive/ansi.c new file mode 100644 index 0000000..40fbf41 --- /dev/null +++ b/src/exhaustive/ansi.c @@ -0,0 +1,188 @@ + +#include <misc/config.h> +#include <misc/types.h> +#include "ansi.h" +#include "gen/seed.h" +#include "gen/field.h" +#include "util/bits.h" +#include "util/memory.h" +#include "io/output.h" + + +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); +} + +static void seed_hash(seed_t *seed) { + seed->hash20 = try_malloc(20); + bits_sha1(seed->seed, seed->hash20); +} + +static void seed_tsh(seed_t *seed, const config_t *cfg) { + pari_sp ltop = avma; + seed->ansi.t = utoi(cfg->bits); + seed->ansi.s = floorr( + rdivii(subis(seed->ansi.t, 1), stoi(160), DEFAULTPREC)); + seed->ansi.h = subii(seed->ansi.t, mulis(seed->ansi.s, 160)); + gerepileall(ltop, 3, &seed->ansi.t, &seed->ansi.s, &seed->ansi.h); +} + +GENERATOR(ansi_gen_seed_random) { + seed_t *seed = seed_new(); + seed->seed = bits_from_i(random_int(160)); + seed_hash(seed); + seed_tsh(seed, cfg); + curve->seed = seed; + return 1; +} + +GENERATOR(ansi_gen_seed_argument) { + seed_t *seed = seed_new(); + seed->seed = seed_stoi(cfg->seed); + seed_hash(seed); + seed_tsh(seed, cfg); + curve->seed = seed; + return 1; +} + +GENERATOR(ansi_gen_seed_input) { + pari_sp ltop = avma; + + GEN str = input_string("seed:"); + const char *cstr = GSTR(str); + if (!ansi_seed_valid(cstr)) { + fprintf(err, "SEED must be at least 160 bits(40 hex characters).\n"); + avma = ltop; + return 0; + } + + seed_t *seed = seed_new(); + seed->seed = seed_stoi(cstr); + seed_hash(seed); + seed_tsh(seed, cfg); + curve->seed = seed; + return 1; +} + +static bits_t *seed_process(seed_t *seed, const bits_t *first) { + pari_sp ltop = avma; + + bits_t *result = bits_copy(first); + + long is = itos(seed->ansi.s); + GEN seedi = bits_to_i(seed->seed); + GEN two_g = int2n(seed->seed->bitlen); + + for (long i = 1; i <= is; ++i) { + pari_sp btop = avma; + GEN inner = addis(seedi, i); + inner = modii(inner, two_g); + + bits_t *to_hash = bits_from_i(inner); + if (to_hash->bitlen < seed->seed->bitlen) { + bits_lengthenz(to_hash, seed->seed->bitlen - to_hash->bitlen); + } + unsigned char hashout[20]; + bits_sha1(to_hash, hashout); + bits_t *Wi = bits_from_raw(hashout, 160); + bits_concatz(result, Wi, NULL); + + bits_free(&to_hash); + bits_free(&Wi); + avma = btop; + } + + avma = ltop; + return result; +} + +UNROLL(ansi_unroll_seed) { + seed_free(&curve->seed); + return -1; +} + +static GENERATOR(ansi_gen_equation_fp) { + pari_sp ltop = avma; + bits_t *c0 = bits_from_raw(curve->seed->hash20, 160); + bits_shortenz(c0, 160 - itos(curve->seed->ansi.h)); + + bits_t *W0 = bits_copy(c0); + SET_BIT(W0->bits, 0, 0); + + bits_t *W = seed_process(curve->seed, W0); + + long ti = itos(curve->seed->ansi.t); + GEN r = gen_0; + for (long i = 1; i <= ti; ++i) { + GEN Wi = stoi(GET_BIT(W->bits, i - 1)); + r = addii(r, mulii(Wi, int2n(ti - i))); + } + curve->seed->ansi.r = r; + + GEN r_inv = Fp_invsafe(r, curve->field); + GEN a; + GEN b2; + do { + a = random_int(cfg->bits); + b2 = mulii(powis(a, 3), r_inv); + }while (!Fp_issquare(b2, curve->field)); + GEN b = Fp_sqrt(b2, curve->field); + + curve->a = a; + curve->b = b; + + gerepileall(ltop, 3, &curve->seed->ansi.r, &curve->a, &curve->b); + bits_free(&c0); + bits_free(&W0); + bits_free(&W); + return 1; +} + +static GENERATOR(ansi_gen_equation_f2m) { + pari_sp ltop = avma; + bits_t *b0 = bits_from_raw(curve->seed->hash20, 160); + bits_shortenz(b0, 160 - itos(curve->seed->ansi.h)); + + bits_t *b = seed_process(curve->seed, b0); + GEN ib = bits_to_i(b); + if (gequal0(ib)) { + avma = ltop; + return -3; + } + GEN a = random_int(cfg->bits); + curve->a = field_ielement(curve->field, a); + curve->b = field_ielement(curve->field, ib); + + gerepileall(ltop, 2, &curve->a, &curve->b); + bits_free(&b0); + bits_free(&b); + return 1; +} + +GENERATOR(ansi_gen_equation) { + switch (cfg->field) { + case FIELD_PRIME: return ansi_gen_equation_fp(curve, cfg, args); + case FIELD_BINARY: return ansi_gen_equation_f2m(curve, cfg, args); + default: pari_err_BUG("Field not prime or binary?"); + return INT_MIN; /* NOT REACHABLE */ + } +} diff --git a/src/exhaustive/ansi.h b/src/exhaustive/ansi.h new file mode 100644 index 0000000..74e787e --- /dev/null +++ b/src/exhaustive/ansi.h @@ -0,0 +1,55 @@ + +#ifndef ECGEN_ANSI_H +#define ECGEN_ANSI_H + +#include "misc/types.h" + +bool ansi_seed_valid(const char *hex_str); + +/** + * @brief + * @param curve A curve_t being generated + * @param cfg An application config + * @param args unused + * @return state diff + */ +GENERATOR(ansi_gen_seed_random); + +/** + * @brief + * @param curve A curve_t being generated + * @param cfg An application config + * @param args unused + * @return state diff + */ +GENERATOR(ansi_gen_seed_argument); + +/** + * @brief + * @param curve A curve_t being generated + * @param cfg An application config + * @param args unused + * @return state diff + */ +GENERATOR(ansi_gen_seed_input); + +/** + * @brief + * @param curve + * @param cfg + * @param from + * @param to + * @return + */ +UNROLL(ansi_unroll_seed); + +/** + * @brief + * @param curve A curve_t being generated + * @param cfg An application config + * @param args unused + * @return state diff + */ +GENERATOR(ansi_gen_equation); + +#endif //ECGEN_ANSI_H diff --git a/src/exhaustive/arg.h b/src/exhaustive/arg.h index 1a4d0ed..415008c 100644 --- a/src/exhaustive/arg.h +++ b/src/exhaustive/arg.h @@ -8,7 +8,7 @@ #ifndef ECGEN_ARG_H #define ECGEN_ARG_H -#include "gen/types.h" +#include "misc/types.h" /** * @brief diff --git a/src/exhaustive/exhaustive.c b/src/exhaustive/exhaustive.c index 6b77f3a..0506409 100644 --- a/src/exhaustive/exhaustive.c +++ b/src/exhaustive/exhaustive.c @@ -2,33 +2,35 @@ * ecgen, tool for generating Elliptic curve domain parameters * Copyright (C) 2017 J08nY */ +#include <misc/config.h> #include "exhaustive.h" #include "anomalous.h" +#include "ansi.h" #include "gen/curve.h" #include "gen/equation.h" #include "gen/field.h" #include "gen/gens.h" #include "gen/order.h" #include "gen/point.h" -#include "gen/seed.h" #include "io/output.h" #include "util/memory.h" static void exhaustive_ginit(gen_t *generators, const config_t *cfg) { - if (cfg->from_seed) { + if (cfg->ansi) { // setup ANSI X9.62 generators if (cfg->seed) { - generators[OFFSET_SEED] = &seed_gen_argument; + generators[OFFSET_SEED] = &ansi_gen_seed_argument; } else { if (cfg->random) { - generators[OFFSET_SEED] = &seed_gen_random; + generators[OFFSET_SEED] = &ansi_gen_seed_random; } else { - generators[OFFSET_SEED] = &seed_gen_input; + generators[OFFSET_SEED] = &ansi_gen_seed_input; } } - generators[OFFSET_A] = &a_gen_seed; - generators[OFFSET_B] = &b_gen_seed; - generators[OFFSET_CURVE] = &curve_gen_seed; + generators[OFFSET_A] = &gen_skip; + generators[OFFSET_B] = &ansi_gen_equation; + generators[OFFSET_CURVE] = &curve_gen_nonzero; + generators[OFFSET_ORDER] = &order_gen_any; } else { // setup normal generators generators[OFFSET_SEED] = &gen_skip; @@ -142,7 +144,11 @@ static void exhaustive_ainit(arg_t **argss, const config_t *cfg) { } void exhaustive_uinit(unroll_t *unrolls, const config_t *cfg) { - unrolls[OFFSET_SEED] = &unroll_skip; + if (cfg->ansi) { + unrolls[OFFSET_SEED] = &ansi_unroll_seed; + } else { + unrolls[OFFSET_SEED] = &unroll_skip; + } unrolls[OFFSET_FIELD] = &unroll_skip; unrolls[OFFSET_A] = &unroll_skip; unrolls[OFFSET_B] = &unroll_skip; @@ -176,8 +182,7 @@ int exhaustive_gen_retry(curve_t *curve, const config_t *cfg, if (diff <= 0) { if (diff == INT_MIN || state + diff < 0) { - fprintf(err, "Error generating a curve. state = %i\n", - state); + fprintf(err, "Error generating a curve. state = %i\n", state); return 0; } // record try diff --git a/src/exhaustive/exhaustive.h b/src/exhaustive/exhaustive.h index 3b26d73..446dff2 100644 --- a/src/exhaustive/exhaustive.h +++ b/src/exhaustive/exhaustive.h @@ -8,7 +8,7 @@ #ifndef ECGEN_GENERATORS_H #define ECGEN_GENERATORS_H -#include "gen/types.h" +#include "misc/types.h" /** * diff --git a/src/gen/curve.c b/src/gen/curve.c index ea5ed95..3a8d00d 100644 --- a/src/gen/curve.c +++ b/src/gen/curve.c @@ -2,6 +2,7 @@ * ecgen, tool for generating Elliptic curve domain parameters * Copyright (C) 2017 J08nY */ +#include <misc/config.h> #include "curve.h" #include "point.h" #include "seed.h" @@ -130,29 +131,6 @@ GENERATOR(curve_gen_nonzero) { } } -static int curve_gen_seed_fp(curve_t *curve, const config_t *cfg, arg_t *args) { - // TODO implement - return INT_MIN; -} - -static int curve_gen_seed_f2m(curve_t *curve, const config_t *cfg, - arg_t *args) { - // TODO implement - return INT_MIN; -} - -GENERATOR(curve_gen_seed) { - switch (typ(curve->field)) { - case t_INT: - return curve_gen_seed_fp(curve, cfg, args); - case t_FFELT: - return curve_gen_seed_f2m(curve, cfg, args); - default: - pari_err_TYPE("curve_gen_seed", curve->field); - return INT_MIN; /* NOT REACHABLE */ - } -} - UNROLL(curve_unroll) { if (curve->curve) { obj_free(curve->curve); diff --git a/src/gen/curve.h b/src/gen/curve.h index 2e7651f..f5e6553 100644 --- a/src/gen/curve.h +++ b/src/gen/curve.h @@ -9,7 +9,7 @@ #define ECGEN_CURVE_H #include <pari/pari.h> -#include "types.h" +#include "misc/types.h" /** * GENERATOR(gen_t) @@ -35,18 +35,6 @@ GENERATOR(curve_gen_any); */ GENERATOR(curve_gen_nonzero); -/** - * GENERATOR(gen_t) - * Creates a curve GEN in curve_t curve from field, a and b. Using the ANSI - * X9.62 verifiably random algorithm. - * Succeeds if a curve exists(non-zero discriminant). - * - * @param curve A curve_t being generated - * @param cfg An application config - * @param args unused - * @return state diff - */ -GENERATOR(curve_gen_seed); /** * diff --git a/src/gen/equation.c b/src/gen/equation.c index 9524df7..33d41a9 100644 --- a/src/gen/equation.c +++ b/src/gen/equation.c @@ -56,10 +56,6 @@ GENERATOR(a_gen_one) { return 1; } -GENERATOR(a_gen_seed) { - // TODO implement - return INT_MIN; -} GENERATOR(b_gen_random) { curve->b = genrand(curve->field); @@ -111,11 +107,6 @@ GENERATOR(b_gen_one) { return 1; } -GENERATOR(b_gen_seed) { - // TODO implement - return INT_MIN; -} - void equation_quit(void) { if (a && isclone(a)) { gunclone(a); diff --git a/src/gen/equation.h b/src/gen/equation.h index 58e2e6e..665c153 100644 --- a/src/gen/equation.h +++ b/src/gen/equation.h @@ -8,7 +8,7 @@ #ifndef ECGEN_EQUATION_H #define ECGEN_EQUATION_H -#include "types.h" +#include "misc/types.h" /** * GENERATOR(gen_t) diff --git a/src/gen/field.c b/src/gen/field.c index 482bcc5..9a908cc 100644 --- a/src/gen/field.c +++ b/src/gen/field.c @@ -13,7 +13,8 @@ static GEN field_binaryr(unsigned long bits) { if (poly_exists(bits)) { return poly_find_gen(bits); } else { - fprintf(err, "Unable to find a suitable binary field. Use an explicit one."); + fprintf(err, + "Unable to find a suitable binary field. Use an explicit one."); exit(1); } } diff --git a/src/gen/field.h b/src/gen/field.h index 04af2c6..da31298 100644 --- a/src/gen/field.h +++ b/src/gen/field.h @@ -8,7 +8,7 @@ #ifndef ECGEN_FIELD_H #define ECGEN_FIELD_H -#include "types.h" +#include "misc/types.h" /** * GENERATOR(gen_t) diff --git a/src/gen/gens.h b/src/gen/gens.h index f46efbf..c9e8169 100644 --- a/src/gen/gens.h +++ b/src/gen/gens.h @@ -9,7 +9,7 @@ #ifndef ECGEN_GENS_H #define ECGEN_GENS_H -#include "types.h" +#include "misc/types.h" /** * GENERATOR(gen_t) diff --git a/src/gen/order.h b/src/gen/order.h index da62c4d..e798012 100644 --- a/src/gen/order.h +++ b/src/gen/order.h @@ -8,7 +8,7 @@ #ifndef ECGEN_ORDER_H #define ECGEN_ORDER_H -#include "types.h" +#include "misc/types.h" /** * GENERATOR(gen_t) diff --git a/src/gen/point.h b/src/gen/point.h index c8cae17..fdca6f7 100644 --- a/src/gen/point.h +++ b/src/gen/point.h @@ -8,7 +8,7 @@ #ifndef ECGEN_POINT_H #define ECGEN_POINT_H -#include "types.h" +#include "misc/types.h" /** * diff --git a/src/gen/seed.c b/src/gen/seed.c index 505493a..1653a50 100644 --- a/src/gen/seed.c +++ b/src/gen/seed.c @@ -4,13 +4,21 @@ */ #include "seed.h" +#include <misc/config.h> #include "io/output.h" +#include "misc/types.h" +#include "util/bits.h" #include "util/memory.h" seed_t *seed_new(void) { return try_calloc(sizeof(seed_t)); } seed_t *seed_copy(const seed_t *src, seed_t *dest) { - if (src->seed) dest->seed = gcopy(src->seed); + if (src->seed) { + dest->seed = bits_copy(src->seed); + } + if (src->hash20) { + dest->hash20 = try_memdup(src->hash20, 20); + } return dest; } @@ -20,8 +28,7 @@ seed_t *seed_new_copy(const seed_t *src) { } seed_t *seed_clone(const seed_t *src, seed_t *dest) { - if (src->seed) dest->seed = gclone(src->seed); - return dest; + return seed_copy(src, dest); } seed_t *seed_new_clone(const seed_t *src) { @@ -31,75 +38,14 @@ seed_t *seed_new_clone(const seed_t *src) { void seed_free(seed_t **seed) { if (*seed) { - if ((*seed)->seed && isclone((*seed)->seed)) { - gunclone((*seed)->seed); + if ((*seed)->seed) { + bits_free(&(*seed)->seed); + } + if ((*seed)->hash20) { + try_free((*seed)->hash20); } try_free(*seed); *seed = NULL; } } -static GEN seed_stoi(const char *cstr) { - pari_sp ltop = avma; - GEN seed = gen_0; - - size_t len = strlen(cstr); - for (size_t i = 0; i < len; ++i) { - pari_sp btop = avma; - GEN s = stoi(cstr[i]); - s = shifti(s, (len - i - 1) * 8); - seed = addii(seed, s); - gerepileall(btop, 1, &seed); - } - - return gerepilecopy(ltop, seed); -} - -static char *seed_itos(GEN seed) { - pari_sp ltop = avma; - GEN bits = binary_zv(seed); - - long len = glength(bits); - long bytes = (len / 8) + (len % 8 == 0 ? 0 : 1); - char *result = try_malloc((size_t)bytes); - - for (long i = 0; i < len; ++i) { - // TODO - } - avma = ltop; - return result; -} - -GENERATOR(seed_gen_random) { - curve->seed = seed_new(); - curve->seed->seed = random_int(160); - curve->seed->raw = seed_itos(curve->seed->seed); - curve->seed->raw_len = strlen(curve->seed->raw); - return 1; -} - -GENERATOR(seed_gen_argument) { - curve->seed = seed_new(); - curve->seed->seed = seed_stoi(cfg->seed); - curve->seed->raw = cfg->seed; - curve->seed->raw_len = strlen(cfg->seed); - return 1; -} - -GENERATOR(seed_gen_input) { - pari_sp ltop = avma; - - GEN str = input_string("seed:"); - const char *cstr = GSTR(str); - if (strlen(cstr) < 20) { - fprintf(err, "SEED must be at least 160 bits(20 characters).\n"); - avma = ltop; - return 0; - } - - GEN seed = seed_stoi(cstr); - - curve->seed = seed_new(); - curve->seed->seed = gerepilecopy(ltop, seed); - return 1; -} diff --git a/src/gen/seed.h b/src/gen/seed.h index 82eb499..c89fc1d 100644 --- a/src/gen/seed.h +++ b/src/gen/seed.h @@ -9,16 +9,16 @@ #define ECGEN_SEED_H #include "io/input.h" -#include "types.h" +#include "misc/types.h" /** - * + * @brief * @return */ seed_t *seed_new(void); /** - * + * @brief * @param src * @param dest * @return @@ -26,14 +26,14 @@ seed_t *seed_new(void); seed_t *seed_copy(const seed_t *src, seed_t *dest); /** - * + * @brief * @param src * @return */ seed_t *seed_new_copy(const seed_t *src); /** - * + * @brief * @param src * @param dest * @return @@ -41,43 +41,17 @@ seed_t *seed_new_copy(const seed_t *src); seed_t *seed_clone(const seed_t *src, seed_t *dest); /** - * + * @brief * @param src * @return */ seed_t *seed_new_clone(const seed_t *src); /** - * + * @brief * @param seed */ void seed_free(seed_t **seed); -/** - * - * @param curve A curve_t being generated - * @param cfg An application config - * @param args unused - * @return state diff - */ -GENERATOR(seed_gen_random); - -/** - * - * @param curve A curve_t being generated - * @param cfg An application config - * @param args unused - * @return state diff - */ -GENERATOR(seed_gen_argument); - -/** - * - * @param curve A curve_t being generated - * @param cfg An application config - * @param args unused - * @return state diff - */ -GENERATOR(seed_gen_input); #endif // ECGEN_SEED_H diff --git a/src/invalid/invalid.h b/src/invalid/invalid.h index 035692c..a08c5d8 100644 --- a/src/invalid/invalid.h +++ b/src/invalid/invalid.h @@ -8,7 +8,7 @@ #ifndef ECGEN_INVALID_H #define ECGEN_INVALID_H -#include "io/config.h" +#include "misc/config.h" /** * diff --git a/src/invalid/invalid_thread.h b/src/invalid/invalid_thread.h index bedaf60..0f1b4d0 100644 --- a/src/invalid/invalid_thread.h +++ b/src/invalid/invalid_thread.h @@ -9,7 +9,7 @@ #define ECGEN_INVALID_THREAD_H #include <pthread.h> -#include "gen/types.h" +#include "misc/types.h" typedef enum { STATE_FREE, STATE_GENERATING, STATE_GENERATED } state_e; diff --git a/src/io/cli.c b/src/io/cli.c index 1cbf3b9..4545e7f 100644 --- a/src/io/cli.c +++ b/src/io/cli.c @@ -5,7 +5,8 @@ #include "cli.h" #include <string.h> #include <unistd.h> -#include "config.h" +#include "misc/config.h" +#include "exhaustive/ansi.h" char cli_doc[] = "ecgen, tool for generating Elliptic curve domain parameters.\v(C) 2017 " @@ -18,7 +19,7 @@ enum opt_keys { OPT_PRIME = 'p', OPT_COFACTOR = 'k', OPT_RANDOM = 'r', - OPT_SEED = 's', + OPT_ANSI = 's', OPT_INVALID = 'i', OPT_ORDER = 'n', OPT_KOBLITZ = 'K', @@ -51,7 +52,7 @@ struct argp_option cli_options[] = { {"unique", OPT_UNIQUE, 0, 0, "Generate a curve with only one generator.", 2}, {"anomalous", OPT_ANOMALOUS, 0, 0, "Generate an anomalous curve (of trace one, with field order equal to curve order).", 2}, {"points", OPT_POINTS, "TYPE", 0, "Generate points of given type (random/prime/all/nonprime/none).", 2}, - {"seed", OPT_SEED, "SEED", OPTION_ARG_OPTIONAL, "Generate a curve from SEED (ANSI X9.62 verifiable procedure). **NOT IMPLEMENTED**", 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}, {"order", OPT_ORDER, "ORDER", 0, "Generate a curve with given order (using Complex Multiplication). **NOT IMPLEMENTED**", 2}, {"count", OPT_COUNT, "COUNT", 0, "Generate multiple curves.", 2}, @@ -197,14 +198,13 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) { } break; } - case OPT_SEED: - cfg->from_seed = true; + case OPT_ANSI: + cfg->ansi = true; if (arg) { - // ANSI X9.62 specifies seed as at least 160 bits in length. - if (strlen(arg) < 20) { + if (!ansi_seed_valid(arg)) { argp_failure( state, 1, 0, - "SEED must be at least 160 bits (20 characters)."); + "SEED must be at least 160 bits (40 characters)."); } cfg->seed = arg; } @@ -236,13 +236,13 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) { } // Invalid is not prime or seed by definition. if (cfg->invalid && - (cfg->prime || cfg->from_seed || cfg->cofactor)) { + (cfg->prime || cfg->ansi || cfg->cofactor)) { // not seed, not prime argp_failure(state, 1, 0, "Invalid curve generation can not generate curves " "from seed, exhaustive or prime order."); } - if (cfg->cm && (cfg->prime || cfg->from_seed || cfg->invalid || + if (cfg->cm && (cfg->prime || cfg->ansi || cfg->invalid || cfg->cofactor || cfg->anomalous)) { argp_failure(state, 1, 0, "Fixed order curve generation can not generate " @@ -251,7 +251,7 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) { "prime."); } if (cfg->anomalous && - (cfg->binary_field || cfg->cofactor || cfg->from_seed || + (cfg->binary_field || cfg->cofactor || cfg->ansi || cfg->cm || cfg->invalid || cfg->koblitz)) { argp_failure( state, 1, 0, diff --git a/src/io/input.c b/src/io/input.c index 2c0398a..f86afe4 100644 --- a/src/io/input.c +++ b/src/io/input.c @@ -26,20 +26,8 @@ static GEN input_i(const char *prompt, unsigned long bits) { free(line); return gen_m1; } - for (size_t i = 0, j = 0; (line[j] = line[i]); j += !isspace(line[i++])); - -/* if (len <= 3 || !(line[0] == '0' && (line[1] == 'x' || line[1] == 'X'))) { - char *new_line = try_realloc(line, (size_t)(len + 2)); - memmove(new_line + 2, new_line, (size_t)len); - new_line[0] = '0'; - new_line[1] = 'x'; - if (!feof(in)) { - new_line[len + 1] = 0; - } else { - new_line[len + 2] = 0; - } - line = new_line; - }*/ + for (size_t i = 0, j = 0; (line[j] = line[i]); j += !isspace(line[i++])) + ; pari_sp ltop = avma; GEN in = strtoi(line); diff --git a/src/io/input.h b/src/io/input.h index 2759973..eb836e2 100644 --- a/src/io/input.h +++ b/src/io/input.h @@ -8,7 +8,7 @@ #ifndef ECGEN_INPUT_H #define ECGEN_INPUT_H -#include "gen/types.h" +#include "misc/types.h" #include "util/random.h" /** diff --git a/src/io/output.c b/src/io/output.c index 2d05bec..4e951a2 100644 --- a/src/io/output.c +++ b/src/io/output.c @@ -5,6 +5,7 @@ #include "output.h" #include <parson/parson.h> +#include "util/bits.h" #include "gen/field.h" #include "util/memory.h" @@ -29,23 +30,23 @@ char *output_scsv(curve_t *curve, const config_t *cfg) { switch (cfg->field) { case FIELD_PRIME: params[OFFSET_FIELD] = - pari_sprintf("%P0#*x", cfg->hex_digits, curve->field); + pari_sprintf("%P0#*x", cfg->hex_digits, curve->field); break; case FIELD_BINARY: { GEN field = field_params(curve->field); params[OFFSET_FIELD] = - pari_sprintf("%P#x,%P#x,%P#x,%P#x", gel(field, 1), - gel(field, 2), gel(field, 3), gel(field, 4)); + pari_sprintf("%P#x,%P#x,%P#x,%P#x", gel(field, 1), + gel(field, 2), gel(field, 3), gel(field, 4)); break; } } if (curve->a) params[OFFSET_A] = - pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->a)); + pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->a)); if (curve->b) params[OFFSET_B] = - pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->b)); + pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->b)); if (curve->generators) { char *gens[curve->ngens]; @@ -55,8 +56,8 @@ char *output_scsv(curve_t *curve, const config_t *cfg) { GEN x = field_elementi(gel(generator->point, 1)); GEN y = field_elementi(gel(generator->point, 2)); gens[i] = pari_sprintf("%P0#*x,%P0#*x,%P#x,%P#x", cfg->hex_digits, - x, cfg->hex_digits, y, generator->order, - generator->cofactor); + x, cfg->hex_digits, y, generator->order, + generator->cofactor); len += strlen(gens[i]); } size_t lenn = sizeof(char) * (len + curve->ngens); @@ -70,7 +71,7 @@ char *output_scsv(curve_t *curve, const config_t *cfg) { if (curve->order) params[OFFSET_ORDER] = - pari_sprintf("%P0#*x", cfg->hex_digits, curve->order); + pari_sprintf("%P0#*x", cfg->hex_digits, curve->order); if (curve->points) { char *points[curve->npoints]; @@ -80,7 +81,7 @@ char *output_scsv(curve_t *curve, const config_t *cfg) { GEN x = field_elementi(gel(point->point, 1)); GEN y = field_elementi(gel(point->point, 2)); points[i] = pari_sprintf("%P0#*x,%P0#*x,%P#x", cfg->hex_digits, x, - cfg->hex_digits, y, point->order); + cfg->hex_digits, y, point->order); len += strlen(points[i]); } size_t lenn = sizeof(char) * (len + curve->npoints); @@ -150,9 +151,20 @@ static JSON_Value *output_jjson(curve_t *curve, const config_t *cfg) { pari_free(e3); break; } - default: fprintf(err, "Error, field has unknown amount of elements.\n"); + default: + fprintf(err, "Error, field has unknown amount of elements.\n"); exit(1); } + if (curve->seed) { + char *hex_str = bits_to_hex(curve->seed->seed); + char *hex = try_calloc(strlen(hex_str) + 3); + hex[0] = '0'; + hex[1] = 'x'; + strcat(hex, hex_str); + json_object_set_string(root_object, "seed", hex); + try_free(hex_str); + try_free(hex); + } char *a = pari_sprintf("%P0#*x", cfg->hex_digits, field_elementi(curve->a)); json_object_set_string(root_object, "a", a); @@ -172,13 +184,13 @@ static JSON_Value *output_jjson(curve_t *curve, const config_t *cfg) { JSON_Object *point_object = json_value_get_object(point_value); char *x = pari_sprintf( - "%P0#*x", cfg->hex_digits, - field_elementi(gel(curve->generators[i]->point, 1))); + "%P0#*x", cfg->hex_digits, + field_elementi(gel(curve->generators[i]->point, 1))); json_object_set_string(point_object, "x", x); pari_free(x); char *y = pari_sprintf( - "%P0#*x", cfg->hex_digits, - field_elementi(gel(curve->generators[i]->point, 2))); + "%P0#*x", cfg->hex_digits, + field_elementi(gel(curve->generators[i]->point, 2))); json_object_set_string(point_object, "y", y); pari_free(y); char *p_order = pari_sprintf("%P#x", curve->generators[i]->order); @@ -186,7 +198,7 @@ static JSON_Value *output_jjson(curve_t *curve, const config_t *cfg) { pari_free(p_order); if (curve->generators[i]->cofactor) { char *cofactor = - pari_sprintf("%P#x", curve->generators[i]->cofactor); + pari_sprintf("%P#x", curve->generators[i]->cofactor); json_object_set_string(point_object, "cofactor", cofactor); pari_free(cofactor); } @@ -206,13 +218,13 @@ static JSON_Value *output_jjson(curve_t *curve, const config_t *cfg) { JSON_Object *point_object = json_value_get_object(point_value); char *x = - pari_sprintf("%P0#*x", cfg->hex_digits, - field_elementi(gel(curve->points[i]->point, 1))); + pari_sprintf("%P0#*x", cfg->hex_digits, + field_elementi(gel(curve->points[i]->point, 1))); json_object_set_string(point_object, "x", x); pari_free(x); char *y = - pari_sprintf("%P0#*x", cfg->hex_digits, - field_elementi(gel(curve->points[i]->point, 2))); + pari_sprintf("%P0#*x", cfg->hex_digits, + field_elementi(gel(curve->points[i]->point, 2))); json_object_set_string(point_object, "y", y); pari_free(y); char *p_order = pari_sprintf("%P#x", curve->points[i]->order); @@ -220,7 +232,7 @@ static JSON_Value *output_jjson(curve_t *curve, const config_t *cfg) { pari_free(p_order); if (curve->points[i]->cofactor) { char *cofactor = - pari_sprintf("%P#x", curve->points[i]->cofactor); + pari_sprintf("%P#x", curve->points[i]->cofactor); json_object_set_string(point_object, "cofactor", cofactor); pari_free(cofactor); } diff --git a/src/io/output.h b/src/io/output.h index 586f4e8..6c241d5 100644 --- a/src/io/output.h +++ b/src/io/output.h @@ -10,7 +10,7 @@ #include <pari/pari.h> #include <stdbool.h> -#include "gen/types.h" +#include "misc/types.h" #ifdef DEBUG diff --git a/src/math/subgroups.c b/src/math/subgroups.c index 93526ae..45523ad 100644 --- a/src/math/subgroups.c +++ b/src/math/subgroups.c @@ -54,6 +54,7 @@ static GEN subgroups_divisors(GEN order) { * @return a t_VEC of factors */ static GEN subgroups_2n_factors(GEN factors, size_t min_bits) { + pari_sp ltop = avma; long nprimes = glength(factors); if (nprimes == min_bits) return NULL; GEN amount = int2n(nprimes); @@ -77,17 +78,8 @@ static GEN subgroups_2n_factors(GEN factors, size_t min_bits) { avma = btop; } } - GEN sorted = sort(groups); - size_t k = 1; - for (size_t j = 1; j <= i; j++) { - GEN k_value = gel(sorted, k); - GEN j_value = gel(sorted, j); - if (!gequal(k_value, j_value)) { - gel(sorted, ++k) = j_value; - } - } - sorted = vec_shorten(sorted, k); - return sorted; + GEN ret = gtoset(groups); + return gerepilecopy(ltop, ret); } /** diff --git a/src/math/subgroups.h b/src/math/subgroups.h index fee095b..1c11d4c 100644 --- a/src/math/subgroups.h +++ b/src/math/subgroups.h @@ -9,7 +9,7 @@ #define ECGEN_SUBGROUPS_H #include <pari/pari.h> -#include "gen/types.h" +#include "misc/types.h" /** * @brief Enumerates prime subgroup orders of a given curve. diff --git a/src/io/config.h b/src/misc/config.h index 0894b5e..7b9a9dc 100644 --- a/src/io/config.h +++ b/src/misc/config.h @@ -41,7 +41,7 @@ typedef struct { long koblitz_value; bool cofactor; long cofactor_bound; - bool from_seed; + bool ansi; char *seed; bool unique; struct points_s points; diff --git a/src/gen/types.c b/src/misc/types.c index 63d5401..63d5401 100644 --- a/src/gen/types.c +++ b/src/misc/types.c diff --git a/src/gen/types.h b/src/misc/types.h index 5500e85..b75394c 100644 --- a/src/gen/types.h +++ b/src/misc/types.h @@ -10,15 +10,37 @@ #include <limits.h> #include <pari/pari.h> -#include "io/config.h" +#include "misc/config.h" + +/** + * @brief + * @param bits + * @param bitlen + * @param allocated + */ +typedef struct { + unsigned char *bits; + size_t bitlen; + size_t allocated; +} bits_t; /** * @brief */ typedef struct seed_t { - char *raw; - size_t raw_len; - GEN seed; + bits_t *seed; + unsigned char *hash20; + union { + struct { + GEN t; + GEN s; + GEN h; + GEN r; + } ansi; + struct { + bits_t *f; + } brainpool; + }; } seed_t; /** @@ -91,7 +113,8 @@ typedef struct { * @return state diff */ #define GENERATOR(gen_name) \ - int gen_name(curve_t *curve, const config_t *cfg, arg_t *args) + int gen_name(curve_t *curve, const config_t *cfg, arg_t *args) + typedef GENERATOR((*gen_t)); /** @@ -103,8 +126,9 @@ typedef GENERATOR((*gen_t)); * @return */ #define UNROLL(unroll_name) \ - int unroll_name(curve_t *curve, const config_t *cfg, pari_sp from, \ - pari_sp to) + int unroll_name(curve_t *curve, const config_t *cfg, pari_sp from, \ + pari_sp to) + typedef UNROLL((*unroll_t)); /** diff --git a/src/util/bits.c b/src/util/bits.c new file mode 100644 index 0000000..55d5bf3 --- /dev/null +++ b/src/util/bits.c @@ -0,0 +1,430 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ + +#include "bits.h" +#include <sha1/sha1.h> +#include "util/memory.h" + +bits_t *bits_new(size_t bit_len) { + bits_t *result = try_calloc(sizeof(bits_t)); + size_t byte_len = BYTE_LEN(bit_len); + if (byte_len > 0) result->bits = try_calloc(byte_len); + result->allocated = byte_len; + result->bitlen = bit_len; + return result; +} + +bits_t *bits_copy(const bits_t *bits) { + bits_t *result = try_calloc(sizeof(bits_t)); + result->bitlen = bits->bitlen; + result->allocated = bits->allocated; + if (bits->allocated != 0) + result->bits = try_memdup(bits->bits, result->allocated); + return result; +} + +void bits_free(bits_t **bits) { + if (*bits) { + if ((*bits)->bits) { + try_free((*bits)->bits); + } + try_free(*bits); + *bits = NULL; + } +} + +bits_t *bits_from_i(GEN i) { + pari_sp ltop = avma; + GEN bitvec = binary_zv(i); + size_t bit_len = (size_t)glength(bitvec); + bits_t *result = bits_new(bit_len); + for (size_t j = 0; j < bit_len; ++j) { + if (gel(bitvec, j + 1) == (GEN)1) { + result->bits[j / 8] |= 1 << (7 - (j % 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); + for (size_t i = 0; i < nibble_len; ++i) { + char hex = hex_str[i]; + char nibble = 0; + if ('0' <= hex && hex <= '9') { + nibble = (char)(hex - '0'); + } else if ('a' <= hex && hex <= 'f') { + nibble = (char)(hex - 'a' + 10); + } else if ('A' <= hex && hex <= 'F') { + nibble = (char)(hex - 'A' + 10); + } + result->bits[i / 2] |= (nibble << (1 - (i % 2)) * 4); + } + return result; +} + +bits_t *bits_from_bin(const char *bin_str) { + size_t bit_len = strlen(bin_str); + bits_t *result = bits_new(bit_len); + for (size_t i = 0; i < bit_len; ++i) { + if (bin_str[i] == '1') { + result->bits[i / 8] |= 1 << (7 - (i % 8)); + } + } + return result; +} + +bits_t *bits_from_raw(const unsigned char *bits, size_t bit_len) { + bits_t *result = try_calloc(sizeof(bits_t)); + result->bitlen = bit_len; + result->allocated = BYTE_LEN(bit_len); + if (bit_len > 0) result->bits = try_memdup(bits, result->allocated); + return result; +} + +bits_t *bits_from_bitvec(GEN v) { + size_t bit_len = (size_t)glength(v); + bits_t *result = bits_new(bit_len); + for (size_t i = 0; i < bit_len; ++i) { + if (gel(v, i + 1) == (GEN)1) result->bits[i / 8] |= 1 << (7 - (i % 8)); + } + return result; +} + +GEN bits_to_i(const bits_t *bits) { + pari_sp ltop = avma; + GEN result = stoi(0); + for (size_t i = 0; i < bits->bitlen; ++i) { + if (GET_BIT(bits->bits, i) != 0) + result = addii(result, int2n(bits->bitlen - i - 1)); + } + return gerepileupto(ltop, result); +} + +char *bits_to_hex(const bits_t *bits) { + char *result = try_calloc(BYTE_LEN(bits->bitlen) * 2 + 1); + // probably right pad with zeroes, as thats what is actually stored. + for (size_t i = 0; i < BYTE_LEN(bits->bitlen); ++i) { + sprintf(result + (i * 2), "%02x", bits->bits[i]); + } + return result; +} + +char *bits_to_bin(const bits_t *bits) { + char *result = try_calloc(bits->bitlen + 1); + for (size_t i = 0; i < bits->bitlen; ++i) { + sprintf(result + i, "%1u", GET_BIT(bits->bits, i)); + } + return result; +} + +unsigned char *bits_to_raw(const bits_t *bits) { + if (bits->bitlen == 0) { + return NULL; + } + return try_memdup(bits->bits, BYTE_LEN(bits->bitlen)); +} + +size_t bits_to_rawlen(const bits_t *bits) { return BYTE_LEN(bits->bitlen); } + +GEN bits_to_bitvec(const bits_t *bits) { + GEN bitvec = gtovecsmall0(gen_0, bits->bitlen); + for (size_t i = 0; i < bits->bitlen; ++i) { + if (GET_BIT(bits->bits, i) != 0) gel(bitvec, i + 1) = (GEN)1; + } + return bitvec; +} + +static unsigned char or_func(unsigned char one, unsigned char other) { + return one | other; +} + +static unsigned char and_func(unsigned char one, unsigned char other) { + return one & other; +} + +static bits_t *bits_bitwise(const bits_t *one, const bits_t *other, + unsigned char (*bitwise_func)(unsigned char, + unsigned char)) { + const bits_t *shorter; + const bits_t *longer; + if (one->bitlen > other->bitlen) { + shorter = other; + longer = one; + } else { + shorter = one; + longer = other; + } + + bits_t *result = bits_new(longer->bitlen); + for (size_t i = 0; i < longer->bitlen; ++i) { + size_t longer_pos = longer->bitlen - i - 1; + + unsigned char longer_bit = + (unsigned char)GET_BIT(longer->bits, longer_pos); + unsigned char shorter_bit = 0; + if (shorter->bitlen > i) { + size_t shorter_pos = shorter->bitlen - i - 1; + shorter_bit = (unsigned char)GET_BIT(shorter->bits, shorter_pos); + } + + unsigned char result_bit = bitwise_func(longer_bit, shorter_bit); + result->bits[longer_pos / 8] |= result_bit << (7 - (longer_pos % 8)); + } + + return result; +} + +void bits_concatzv(bits_t *one, va_list valist) { + const bits_t *next; + while ((next = va_arg(valist, const bits_t *)) != NULL) { + if (next->bitlen == 0) continue; + size_t new_bitlen = one->bitlen + next->bitlen; + size_t new_alloc = BYTE_LEN(new_bitlen); + if (new_alloc > one->allocated) { + one->bits = try_realloc(one->bits, new_alloc); + for (size_t i = one->allocated; i < new_alloc; ++i) { + one->bits[i] = 0; + } + one->allocated = new_alloc; + } + for (size_t j = 0; j < next->bitlen; ++j) { + SET_BIT(one->bits, one->bitlen + j, GET_BIT(next->bits, j)); + } + one->bitlen = new_bitlen; + } +} + +void bits_concatz(bits_t *one, ...) { + va_list valist; + va_start(valist, one); + + bits_concatzv(one, valist); + + va_end(valist); +} + +bits_t *bits_concat(const bits_t *one, ...) { + va_list valist; + va_start(valist, one); + + bits_t *result = bits_copy(one); + + bits_concatzv(result, valist); + + va_end(valist); + return result; +} + +bits_t *bits_or(const bits_t *one, const bits_t *other) { + return bits_bitwise(one, other, or_func); +} + +bits_t *bits_and(const bits_t *one, const bits_t *other) { + return bits_bitwise(one, other, and_func); +} + +void bits_notz(bits_t *bits) { + if (bits->bitlen == 0) return; + for (size_t i = 0; i < bits->bitlen / 8; ++i) { + bits->bits[i] = ~bits->bits[i]; + } + if (bits->bitlen % 8 != 0) { + size_t mask_len = bits->bitlen % 8; + unsigned char mask = 0; + for (size_t i = 7; i >= 0; --i) { + mask |= 1 << i; + if (--mask_len == 0) break; + } + size_t last_pos = (bits->bitlen / 8); + unsigned char anti_mask = ~mask; + unsigned char last_byte = bits->bits[last_pos]; + bits->bits[last_pos] = (~last_byte & mask) | (last_byte & anti_mask); + } +} + +bits_t *bits_not(const bits_t *bits) { + bits_t *result = bits_copy(bits); + bits_notz(result); + return result; +} + +void bits_rotz(bits_t *bits) { + unsigned char original_bits[bits->allocated]; + for (size_t i = 0; i < bits->allocated; ++i) { + original_bits[i] = bits->bits[i]; + bits->bits[i] = 0; + } + for (size_t i = 0; i < bits->bitlen / 2; ++i) { + size_t left_pos = i; + size_t right_pos = bits->bitlen - i - 1; + unsigned char left_bit = + (unsigned char)GET_BIT(original_bits, left_pos); + unsigned char right_bit = + (unsigned char)GET_BIT(original_bits, right_pos); + bits->bits[right_pos / 8] |= left_bit << (7 - (right_pos % 8)); + bits->bits[left_pos / 8] |= right_bit << (7 - (left_pos % 8)); + } + if (bits->bitlen % 2 == 1) { + size_t middle_pos = bits->bitlen / 2; + + unsigned char middle_bit = + (unsigned char)GET_BIT(original_bits, middle_pos); + bits->bits[middle_pos / 8] |= middle_bit << (7 - (middle_pos % 8)); + } +} + +bits_t *bits_rot(const bits_t *bits) { + bits_t *result = bits_copy(bits); + bits_rotz(result); + return result; +} + +void bits_shiftz(bits_t *bits, long amount) { + if (amount == 0) return; + unsigned char original_bits[bits->allocated]; + for (size_t i = 0; i < bits->allocated; ++i) { + original_bits[i] = bits->bits[i]; + bits->bits[i] = 0; + } + for (size_t i = 0; i < bits->bitlen; ++i) { + unsigned char new_bit = 0; + if ((amount > 0 && i + amount < bits->bitlen) || + (amount < 0 && i >= -amount)) { + new_bit = (unsigned char)GET_BIT(original_bits, i + amount); + } + bits->bits[i / 8] |= new_bit << (7 - (i % 8)); + } +} + +bits_t *bits_shift(const bits_t *bits, long amount) { + bits_t *result = bits_copy(bits); + bits_shiftz(result, amount); + return result; +} + +void bits_shiftrz(bits_t *bits, long amount) { + if (amount == 0) return; + unsigned char original_bits[bits->allocated]; + for (size_t i = 0; i < bits->allocated; ++i) { + original_bits[i] = bits->bits[i]; + bits->bits[i] = 0; + } + for (size_t i = 0; i < bits->bitlen; ++i) { + unsigned char new_bit = 0; + size_t new_pos = 0; + if ((amount > 0 && i + amount < bits->bitlen) || + (amount < 0 && i >= -amount)) { + new_pos = i + amount; + } else if (amount > 0) { + new_pos = (i + amount) % bits->bitlen; + } else if (amount < 0) { + long mod_amount = amount % bits->bitlen; + new_pos = (i + mod_amount) % bits->bitlen; + } + new_bit = (unsigned char)GET_BIT(original_bits, new_pos); + bits->bits[i / 8] |= new_bit << (7 - (i % 8)); + } +} + +bits_t *bits_shiftr(const bits_t *bits, long amount) { + bits_t *result = bits_copy(bits); + bits_shiftrz(result, amount); + return result; +} + +void bits_shiftiz(bits_t *bits, long amount) { + if (amount > 0) { + bits_lengthenz(bits, -amount); + } else if (amount < 0) { + bits_shortenz(bits, amount); + } +} + +bits_t *bits_shifti(const bits_t *bits, long amount) { + bits_t *result = bits_copy(bits); + bits_shiftiz(result, amount); + return result; +} + +void bits_lengthenz(bits_t *bits, long amount) { + size_t abs_amount; + if (amount > 0) { + abs_amount = (size_t)amount; + } else if (amount < 0) { + abs_amount = (size_t)-amount; + } else { + return; + } + size_t new_alloc = BYTE_LEN(bits->bitlen + abs_amount); + if (new_alloc > bits->allocated) { + bits->bits = try_realloc(bits->bits, new_alloc); + for (size_t i = bits->allocated; i < new_alloc; ++i) { + bits->bits[i] = 0; + } + bits->allocated = new_alloc; + } + bits->bitlen += abs_amount; + + if (amount > 0) { + bits_shiftz(bits, -amount); + } +} + +bits_t *bits_lengthen(const bits_t *bits, long amount) { + bits_t *result = bits_copy(bits); + bits_lengthenz(result, amount); + return result; +} + +void bits_shortenz(bits_t *bits, long amount) { + size_t new_bits; + if (amount > 0) { + new_bits = bits->bitlen - amount; + bits_shiftz(bits, amount); + } else if (amount < 0) { + new_bits = bits->bitlen + amount; + for (size_t i = new_bits; i < bits->bitlen; ++i) { + bits->bits[i / 8] &= ~(1 << (7 - (i % 8))); + } + } else { + return; + } + bits->bitlen = new_bits; +} + +bits_t *bits_shorten(const bits_t *bits, long amount) { + bits_t *result = bits_copy(bits); + bits_shortenz(result, amount); + return result; +} + +void bits_sha1(const bits_t *bits, unsigned char hashout[20]) { + SHA_CTX ctx = {0}; + SHA1_Init(&ctx); + SHA1_Update(&ctx, bits->bits, (int)BYTE_LEN(bits->bitlen)); + SHA1_Final(hashout, &ctx); +} + +bool bits_eq(const bits_t *one, const bits_t *other) { + if (one->bitlen != other->bitlen) return false; + if (one->bitlen == 0) return true; + if (memcmp(one->bits, other->bits, one->bitlen / 8) != 0) return false; + if (one->bitlen % 8 != 0) { + size_t mask_len = one->bitlen % 8; + unsigned char mask = 0; + for (size_t i = 7; i >= 0; --i) { + mask |= 1 << i; + if (--mask_len == 0) break; + } + size_t last_byte = (one->bitlen / 8); + unsigned char one_masked = one->bits[last_byte] & mask; + unsigned char other_masked = other->bits[last_byte] & mask; + return one_masked == other_masked; + } + return true; +} diff --git a/src/util/bits.h b/src/util/bits.h new file mode 100644 index 0000000..3ea0dd2 --- /dev/null +++ b/src/util/bits.h @@ -0,0 +1,96 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ + +#ifndef ECGEN_BITS_H +#define ECGEN_BITS_H + +#include "misc/types.h" + +#define BYTE_LEN(bit_len) \ + (((bit_len) % 8 == 0) ? (bit_len) / 8 : ((bit_len) / 8) + 1) + +#define GET_BIT(bit_array, bit_pos) \ + (((bit_array)[(bit_pos) / 8] & (1 << (7 - ((bit_pos) % 8)))) >> \ + (7 - ((bit_pos) % 8))) + +#define SET_BIT(bit_array, bit_pos, bit_value) \ + do { \ + unsigned char val = 1 << (7 - ((bit_pos) % 8)); \ + if ((bit_value) == 1) { \ + (bit_array)[(bit_pos) / 8] |= val; \ + } else { \ + (bit_array)[(bit_pos) / 8] &= ~val; \ + } \ + } while (0); + +bits_t *bits_new(size_t bit_len); + +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_hex(const char *hex_str); + +bits_t *bits_from_bin(const char *bin_str); + +bits_t *bits_from_raw(const unsigned char *bits, size_t bit_len); + +bits_t *bits_from_bitvec(GEN v); + +GEN bits_to_i(const bits_t *bits); + +char *bits_to_hex(const bits_t *bits); + +char *bits_to_bin(const bits_t *bits); + +unsigned char *bits_to_raw(const bits_t *bits); + +size_t bits_to_rawlen(const bits_t *bits); + +GEN bits_to_bitvec(const bits_t *bits); + +void bits_concatz(bits_t *one, ...); + +bits_t *bits_concat(const bits_t *one, ...); + +bits_t *bits_or(const bits_t *one, const bits_t *other); + +bits_t *bits_and(const bits_t *one, const bits_t *other); + +void bits_notz(bits_t *bits); + +bits_t *bits_not(const bits_t *bits); + +void bits_rotz(bits_t *bits); + +bits_t *bits_rot(const bits_t *bits); + +void bits_shiftz(bits_t *bits, long amount); + +bits_t *bits_shift(const bits_t *bits, long amount); + +void bits_shiftrz(bits_t *bits, long amount); + +bits_t *bits_shiftr(const bits_t *bits, long amount); + +void bits_shiftiz(bits_t *bits, long amount); + +bits_t *bits_shifti(const bits_t *bits, long amount); + +void bits_lengthenz(bits_t *bits, long amount); + +bits_t *bits_lengthen(const bits_t *bits, long amount); + +void bits_shortenz(bits_t *bits, long amount); + +bits_t *bits_shorten(const bits_t *bits, long amount); + +void bits_sha1(const bits_t *bits, unsigned char hashout[20]); + +bool bits_eq(const bits_t *one, const bits_t *other); + +#endif // ECGEN_BITS_H diff --git a/src/util/memory.c b/src/util/memory.c index 53f68c9..6051459 100644 --- a/src/util/memory.c +++ b/src/util/memory.c @@ -5,7 +5,6 @@ #include "memory.h" #include <pari/pari.h> - static void *(*malloc_func)(size_t) = pari_malloc; static void *(*calloc_func)(size_t) = pari_calloc; @@ -25,9 +24,7 @@ void *alloc(void *(*fun)(size_t), size_t size) { void *try_malloc(size_t size) { return alloc(malloc_func, size); } -void *try_calloc(size_t size) { - return alloc(calloc_func, size); -} +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); @@ -38,13 +35,22 @@ void *try_realloc(void *ptr, size_t size) { return result; } -void try_free(void *ptr) { - free_func(ptr); +char *try_strdup(const char *str) { + size_t len = strlen(str); + return try_memdup(str, len + 1); +} + +void *try_memdup(const void *mem, size_t len) { + void *result = try_malloc(len); + memcpy(result, mem, len); + return result; } +void try_free(void *ptr) { free_func(ptr); } + void set_mem_funcs(void *(*malloc_fun)(size_t), void *(*calloc_fun)(size_t), - void *(*realloc_fun)(void *, size_t), - void(*free_fun)(void *)) { + void *(*realloc_fun)(void *, size_t), + void (*free_fun)(void *)) { malloc_func = malloc_fun; calloc_func = calloc_fun; realloc_func = realloc_fun; diff --git a/src/util/memory.h b/src/util/memory.h index 7070430..29b2df9 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -34,6 +34,21 @@ void *try_realloc(void *ptr, size_t size); /** * @brief + * @param str + * @return + */ +char *try_strdup(const char *str); + +/** + * @brief + * @param mem + * @param len + * @return + */ +void *try_memdup(const void *mem, size_t len); + +/** + * @brief * @param ptr */ void try_free(void *ptr); @@ -46,7 +61,7 @@ void try_free(void *ptr); * @param free_fun */ void set_mem_funcs(void *(*malloc_fun)(size_t), void *(*calloc_fun)(size_t), - void *(*realloc_fun)(void *, size_t), - void(*free_fun)(void *)); + void *(*realloc_fun)(void *, size_t), + void (*free_fun)(void *)); #endif // ECGEN_MEMORY_H diff --git a/src/util/random.c b/src/util/random.c index bd7b89b..9af43cc 100644 --- a/src/util/random.c +++ b/src/util/random.c @@ -43,9 +43,7 @@ bool random_init(void) { GEN random_prime(unsigned long bits) { pari_sp ltop = avma; - GEN range = gtovec0(gen_0, 2); - gel(range, 1) = powis(gen_2, bits - 1); - gel(range, 2) = powis(gen_2, bits); + GEN range = mkvec2(int2n(bits - 1), int2n(bits)); GEN p; pari_sp btop = avma; @@ -60,9 +58,6 @@ GEN random_prime(unsigned long bits) { GEN random_int(unsigned long bits) { pari_sp ltop = avma; - GEN range = gtovec0(gen_0, 2); - gel(range, 1) = powis(gen_2, bits - 1); - gel(range, 2) = powis(gen_2, bits); - + GEN range = mkvec2(int2n(bits - 1), int2n(bits)); return gerepilecopy(ltop, genrand(range)); } diff --git a/test/Makefile b/test/Makefile index 7ac8236..0aacdeb 100644 --- a/test/Makefile +++ b/test/Makefile @@ -10,7 +10,7 @@ test: ecgen econvert unittest: unit ecgen econvert unit: - cd lib/criterion && mkdir -p build && cd build && cmake .. && cmake --build . + cd lib/criterion && mkdir -p build && cd build && cmake .. >/dev/null && cmake --build . >/dev/null +$(MAKE) -C src all ecgen: diff --git a/test/ecgen.sh b/test/ecgen.sh index 5ec9ccd..76b1bd1 100755 --- a/test/ecgen.sh +++ b/test/ecgen.sh @@ -97,7 +97,7 @@ function cli() { assert_raises "${ecgen} --format=something" 1 assert_raises "${ecgen} --koblitz=2" 1 assert_raises "${ecgen} --points=something" 1 - assert_raises "${ecgen} --seed=some" 1 + assert_raises "${ecgen} --seed=some" 64 assert_raises "${ecgen} 1 2 3" 64 assert_raises "${ecgen} --fp --f2m 1" 1 } diff --git a/test/src/exhaustive/test_ansi.c b/test/src/exhaustive/test_ansi.c new file mode 100644 index 0000000..4217a15 --- /dev/null +++ b/test/src/exhaustive/test_ansi.c @@ -0,0 +1,286 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ + +#include <criterion/criterion.h> +#include <criterion/parameterized.h> +#include "misc/types.h" +#include "math/poly.h" +#include "exhaustive/ansi.h" +#include "gen/seed.h" +#include "gen/field.h" +#include "test/default.h" +#include "test/memory.h" +#include "test/input.h" +#include "test/output.h" +#include "util/bits.h" +#include "util/memory.h" + +void ansi_suite_setup(void) { + default_setup(); + input_setup(); + output_setup(); +} + +void ansi_suite_teardown(void) { + default_teardown(); + input_teardown(); + output_teardown(); +} + +TestSuite(ansi, .init = ansi_suite_setup, .fini = ansi_suite_teardown); + +Test(ansi, test_seed_random) { + curve_t curve = {}; + config_t cfg = {.bits = 256}; + int ret = ansi_gen_seed_random(&curve, &cfg, NULL); + + cr_assert_eq(ret, 1, ); + cr_assert_not_null(curve.seed, ); + + seed_free(&curve.seed); +} + +Test(ansi, test_seed_argument) { + curve_t curve = {}; + char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd"; + config_t cfg = {.seed = seed, .bits = 256}; + int ret = ansi_gen_seed_argument(&curve, &cfg, NULL); + + 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(ansi, test_seed_argument_hex) { + curve_t curve = {}; + char *seed = "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"; + config_t cfg = {.seed = seed, .bits = 256}; + int ret = ansi_gen_seed_argument(&curve, &cfg, NULL); + + 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 + 2, ); + + try_free(hex); + seed_free(&curve.seed); +} + +Test(ansi, test_seed_input) { + curve_t curve = {}; + char *seed = "abcdefabcdefabcdefabcdefabcdefabcdefabcd"; + config_t cfg = {.bits = 256}; + fprintf(write_in, "%s\n", seed); + int ret = ansi_gen_seed_input(&curve, &cfg, NULL); + + 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(ansi, test_seed_input_short) { + curve_t curve = {}; + char *seed = "abcdef"; + config_t cfg = {}; + fprintf(write_in, "%s\n", seed); + int ret = ansi_gen_seed_input(&curve, &cfg, NULL); + + cr_assert_eq(ret, 0, ); +} + +struct prime_params { + size_t bits; + char *p; + char *seed; + char *r; + char *a; + char *b; +}; + +void prime_params_cleanup(struct criterion_test_params *ctp) { + struct prime_params *params = (struct prime_params *)ctp->params; + cr_free(params->p); + cr_free(params->seed); + cr_free(params->r); + cr_free(params->a); + cr_free(params->b); +} + +ParameterizedTestParameters(ansi, test_seed_prime_examples) { + static struct prime_params params[7] = {}; + // Taken from ANSI X9.62 J.5.1 - J.5.3; p. 115 - 117 + params[0].bits = 192; + params[0].p = cr_strdup("fffffffffffffffffffffffffffffffeffffffffffffffff"); + params[0].seed = cr_strdup("3045AE6FC8422F64ED579528D38120EAE12196D5"); + params[0].r = cr_strdup("3099D2BBBFCB2538542DCD5FB078B6EF5F3D6FE2C745DE65"); + params[0].a = cr_strdup("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); + params[0].b = cr_strdup("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"); + params[1].bits = 192; + params[1].p = cr_strdup("fffffffffffffffffffffffffffffffeffffffffffffffff"); + params[1].seed = cr_strdup("31A92EE2029FD10D901B113E990710F0D21AC6B6"); + params[1].r = cr_strdup("15038D1D2E1CAFEE0299F3011C1DC75B3C2A86E135DB1E6B"); + params[1].a = cr_strdup("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); + params[1].b = cr_strdup("CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953"); + params[2].bits = 192; + params[2].p = cr_strdup("fffffffffffffffffffffffffffffffeffffffffffffffff"); + params[2].seed = cr_strdup("C469684435DEB378C4B65CA9591E2A5763059A2E"); + params[2].r = cr_strdup("25191F95024D839546D9A3375639A9967D52F1373BC4EE0B"); + params[2].a = cr_strdup("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); + params[2].b = cr_strdup("22123DC2395A05CAA7423DAECCC94760A7D462256BD56916"); + params[3].bits = 239; + params[3].p = cr_strdup("7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); + params[3].seed = cr_strdup("E43BB460F0B80CC0C0B075798E948060F8321B7D"); + params[3].r = cr_strdup("28B85EC1ECC19EFE769EB741A6D1BA29476AA5A8F2610957D6EFE78D3783"); + params[3].a = cr_strdup("7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC"); + params[3].b = cr_strdup("6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A"); + params[4].bits = 239; + params[4].p = cr_strdup("7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); + params[4].seed = cr_strdup("E8B4011604095303CA3B8099982BE09FCB9AE616"); + params[4].r = cr_strdup("1DF491E44E7CCAF4D1EAD8A6B90DAE09E0D33F2C6CFE7A6BA76E86713D52"); + params[4].a = cr_strdup("7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC"); + params[4].b = cr_strdup("617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C"); + params[5].bits = 239; + params[5].p = cr_strdup("7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff"); + params[5].seed = cr_strdup("7D7374168FFE3471B60A857686A19475D3BFA2FF"); + params[5].r = cr_strdup("3A4F9DC9A6CEFD5F9D1193B9C9968C202430003C2819C2E498618DC58330"); + params[5].a = cr_strdup("7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC"); + params[5].b = cr_strdup("255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E"); + params[6].bits = 256; + params[6].p = cr_strdup("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"); + params[6].seed = cr_strdup("C49D360886E704936A6678E1139D26B7819F7E90"); + params[6].r = cr_strdup("7EFBA1662985BE9403CB055C75D4F7E0CE8D84A9C5114ABCAF3177680104FA0D"); + params[6].a = cr_strdup("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); + params[6].b = cr_strdup("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); + + size_t nb_params = sizeof(params) / sizeof(struct prime_params); + return cr_make_param_array(struct prime_params, params, nb_params, NULL); +} +ParameterizedTest(struct prime_params *param, ansi, test_seed_prime_examples) { + config_t cfg = {}; + cfg.bits = param->bits; + cfg.field = FIELD_PRIME; + cfg.seed = param->seed; + curve_t curve = {}; + bits_t *p = bits_from_hex(param->p); + curve.field = bits_to_i(p); + + int ret = ansi_gen_seed_argument(&curve, &cfg, NULL); + cr_assert_eq(ret, 1,); + + ret = ansi_gen_equation(&curve, &cfg, NULL); + 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),); + + bits_free(&p); + seed_free(&curve.seed); +} + +struct binary_params { + size_t bits; + polynomial_t field; + char *seed; + char *a; + char *b; +}; + +void binary_params_cleanup(struct criterion_test_params *ctp) { + struct binary_params *params = (struct binary_params *)ctp->params; + cr_free(params->seed); + cr_free(params->a); + cr_free(params->b); +} + +ParameterizedTestParameters(ansi, test_seed_binary_examples) { + static struct binary_params params[10] = {}; + // Taken from ANSI X9.62 J.4.1, J.4.3, J.4.5 and J.4.8; p. 107 - 113 + polynomial_t p163 = {163, 9, 3, 2}; + params[0].bits = 163; + params[0].field = p163; + params[0].seed = cr_strdup("D2C0FB15760860DEF1EEF4D696E6768756151754"); + params[0].a = cr_strdup("072546B5435234A422E0789675F432C89435DE5242"); + params[0].b = cr_strdup("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9"); + params[1].bits = 163, + params[1].field = p163; + params[1].seed = cr_strdup("53814C050D44D696E67687561517580CA4E29FFD"); + params[1].a = cr_strdup("0108B39E77C4B108BED981ED0E890E117C511CF072"); + params[1].b = cr_strdup("0667ACEB38AF4E488C407433FFAE4F1C811638DF20"); + params[2].bits = 163; + params[2].field = p163; + params[2].seed = cr_strdup("50CBF1D95CA94D696E676875615175F16A36A3B8"); + params[2].a = cr_strdup("07A526C63D3E25A256A007699F5447E32AE456B50E"); + params[2].b = cr_strdup("03F7061798EB99E238FD6F1BF95B48FEEB4854252B"); + polynomial_t p191 = {191, 10}; + params[3].bits = 191; + params[3].field = p191; + params[3].seed = cr_strdup("4E13CA542744D696E67687561517552F279A8C84"); + params[3].a = cr_strdup("2866537B676752636A68F56554E12640276B649EF7526267"); + params[3].b = cr_strdup("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC"); + params[4].bits = 191; + params[4].field = p191; + params[4].seed = cr_strdup("0871EF2FEF24D696E6768756151758BEE0D95C15"); + params[4].a = cr_strdup("401028774D7777C7B7666D1366EA432071274F89FF01E718"); + params[4].b = cr_strdup("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01"); + params[5].bits = 191; + params[5].field = p191; + params[5].seed = cr_strdup("E053512DC684D696E676875615175067AE786D1F"); + params[5].a = cr_strdup("6C01074756099122221056911C77D77E77A777E7E7E77FCB"); + params[5].b = cr_strdup("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8"); + polynomial_t p239 = {239, 37}; + params[6].bits = 239; + params[6].field = p239; + params[6].seed = cr_strdup("D34B9A4D696E676875615175CA71B920BFEFB05D"); + params[6].a = cr_strdup("32010857077C5431123A46B808906756F543423E8D27877578125778AC76"); + params[6].b = cr_strdup("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16"); + params[7].bits = 239; + params[7].field = p239; + params[7].seed = cr_strdup("2AA6982FDFA4D696E676875615175D266727277D"); + params[7].a = cr_strdup("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F"); + params[7].b = cr_strdup("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B"); + params[8].bits = 239; + params[8].field = p239; + params[8].seed = cr_strdup("9E076F4D696E676875615175E11E9FDD77F92041"); + params[8].a = cr_strdup("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F"); + params[8].b = cr_strdup("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40"); + polynomial_t p359 = {359, 69}; + params[9].bits = 359; + params[9].field = p359; + params[9].seed = cr_strdup("2B354920B724D696E67687561517585BA1332DC6"); + params[9].a = cr_strdup("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557"); + params[9].b = cr_strdup("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988"); + + size_t nb_params = sizeof(params) / sizeof(struct binary_params); + return cr_make_param_array(struct binary_params, params, nb_params, binary_params_cleanup); +} +ParameterizedTest(struct binary_params *param, ansi, test_seed_binary_examples) { + config_t cfg = {}; + cfg.bits = param->bits; + cfg.field = FIELD_BINARY; + cfg.seed = param->seed; + curve_t curve = {}; + curve.field = poly_gen(¶m->field); + + GEN expected_b = bits_to_i(bits_from_hex(param->b)); + bits_t *b = bits_from_i(expected_b); + + int ret = ansi_gen_seed_argument(&curve, &cfg, NULL); + cr_assert_eq(ret, 1,); + + ret = ansi_gen_equation(&curve, &cfg, NULL); + 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/gen/test_point.c b/test/src/gen/test_point.c index 48872be..d77f83d 100644 --- a/test/src/gen/test_point.c +++ b/test/src/gen/test_point.c @@ -5,7 +5,7 @@ #include <criterion/criterion.h> #include "gen/point.h" -#include "test/utils.h" +#include "test/default.h" TestSuite(point, .init = default_setup, .fini = default_teardown); diff --git a/test/src/io/test_cli.c b/test/src/io/test_cli.c index c90bbfa..e5077ef 100644 --- a/test/src/io/test_cli.c +++ b/test/src/io/test_cli.c @@ -3,26 +3,25 @@ * Copyright (C) 2017 J08nY */ -#include "test/utils.h" -#include "io/cli.h" -#include "io/config.h" #include <criterion/criterion.h> #include <unistd.h> +#include "io/cli.h" +#include "misc/config.h" +#include "test/default.h" static struct argp test_argp = {cli_options, cli_parse, cli_args_doc, - cli_doc, 0, cli_filter}; + cli_doc, 0, cli_filter}; TestSuite(cli, .init = default_setup, .fini = default_teardown); - Test(cli, test_memory) { int argc = 4; char *argv[] = {"ecgen", "--memory=2k", "--fp", "1"}; config_t cfg; memset(&cfg, 0, sizeof(cfg)); int ret = argp_parse(&test_argp, argc, argv, 0, 0, &cfg); - cr_assert_eq(ret, 0,); - cr_assert_eq(cfg.memory, 2000,); + cr_assert_eq(ret, 0, ); + cr_assert_eq(cfg.memory, 2000, ); } Test(cli, test_thread_memory) { @@ -31,8 +30,8 @@ Test(cli, test_thread_memory) { config_t cfg; memset(&cfg, 0, sizeof(cfg)); int ret = argp_parse(&test_argp, argc, argv, 0, 0, &cfg); - cr_assert_eq(ret, 0,); - cr_assert_eq(cfg.thread_memory, 2000,); + cr_assert_eq(ret, 0, ); + cr_assert_eq(cfg.thread_memory, 2000, ); } Test(cli, test_threads) { @@ -41,8 +40,8 @@ Test(cli, test_threads) { config_t cfg; memset(&cfg, 0, sizeof(cfg)); int ret = argp_parse(&test_argp, argc, argv, 0, 0, &cfg); - cr_assert_eq(ret, 0,); - cr_assert_eq(cfg.threads, 2,); + cr_assert_eq(ret, 0, ); + cr_assert_eq(cfg.threads, 2, ); } Test(cli, test_auto_threads) { @@ -51,6 +50,6 @@ Test(cli, test_auto_threads) { config_t cfg; memset(&cfg, 0, sizeof(cfg)); int ret = argp_parse(&test_argp, argc, argv, 0, 0, &cfg); - cr_assert_eq(ret, 0,); - cr_assert_eq(cfg.threads, sysconf(_SC_NPROCESSORS_ONLN),); + cr_assert_eq(ret, 0, ); + cr_assert_eq(cfg.threads, sysconf(_SC_NPROCESSORS_ONLN), ); }
\ No newline at end of file diff --git a/test/src/io/test_input.c b/test/src/io/test_input.c index de4ac0f..d32d71c 100644 --- a/test/src/io/test_input.c +++ b/test/src/io/test_input.c @@ -3,92 +3,78 @@ * Copyright (C) 2017 J08nY */ -#include "test/utils.h" -#include "io/input.h" -#include "io/output.h" #include <criterion/criterion.h> +#include "io/input.h" +#include "test/default.h" +#include "test/input.h" +#include "test/output.h" -static FILE *write_in; - -void input_setup() { +void input_suite_setup(void) { default_setup(); - config_t cfg; - memset(&cfg, 0, sizeof(cfg)); - - cfg.output = "/dev/null"; - input_init(&cfg); - output_init(&cfg); - - int in_fd[2]; - pipe(in_fd); - - write_in = fdopen(in_fd[1], "w"); - setlinebuf(write_in); - in = fdopen(in_fd[0], "r"); - err = fopen("/dev/null", "w"); + input_setup(); + output_setup(); } -void input_teardown() { +void input_suite_teardown(void) { default_teardown(); - input_quit(); - output_quit(); - fclose(write_in); + input_teardown(); + output_teardown(); } -TestSuite(input, .init = input_setup, .fini = input_teardown); +TestSuite(input, .init = input_suite_setup, .fini = input_suite_teardown); Test(input, test_prime) { fprintf(write_in, "5\n"); GEN p = input_prime(NULL, 10); - cr_assert(gequal(p, stoi(5)),); + cr_assert(gequal(p, stoi(5)), ); } Test(input, test_prime_nan) { fprintf(write_in, "....\n"); GEN p = input_prime(NULL, 10); - cr_assert(gequal(p, gen_m1),); + cr_assert(gequal(p, gen_m1), ); } Test(input, test_prime_nonprime) { fprintf(write_in, "6\n"); GEN p = input_prime(NULL, 10); - cr_assert(gequal(p, gen_m1),); + cr_assert(gequal(p, gen_m1), ); } Test(input, test_prime_newline) { fprintf(write_in, "\n"); GEN p = input_prime(NULL, 10); - cr_assert(gequal(p, gen_m1),); + cr_assert(gequal(p, gen_m1), ); } Test(input, test_int) { fprintf(write_in, "256\n"); GEN i = input_int(NULL, 10); - cr_assert(gequal(i, stoi(256)),); + cr_assert(gequal(i, stoi(256)), ); } Test(input, test_int_too_big) { fprintf(write_in, "256\n"); GEN i = input_int(NULL, 4); - cr_assert(gequal(i, gen_m1),); + cr_assert(gequal(i, gen_m1), ); } Test(input, test_int_newline) { fprintf(write_in, "\n"); GEN i = input_int(NULL, 4); - cr_assert(gequal(i, gen_m1),); + cr_assert(gequal(i, gen_m1), ); } Test(input, test_str) { fprintf(write_in, "something\n"); GEN s = input_string(NULL); GEN expected = strtoGENstr("something"); - cr_assert(gequal(s, expected),); + cr_assert(gequal(s, expected), ); } Test(input, test_str_newline) { fprintf(write_in, "\n"); GEN s = input_string(NULL); GEN expected = strtoGENstr(""); - cr_assert(gequal(s, expected),); + cr_assert(gequal(s, expected), ); } diff --git a/test/src/math/test_subgroups.c b/test/src/math/test_subgroups.c index b9368d0..8a3c8da 100644 --- a/test/src/math/test_subgroups.c +++ b/test/src/math/test_subgroups.c @@ -5,7 +5,7 @@ #include <criterion/criterion.h> #include "gen/point.h" #include "math/subgroups.h" -#include "test/utils.h" +#include "test/default.h" TestSuite(subgroups, .init = default_setup, .fini = default_teardown); diff --git a/test/src/test/utils.c b/test/src/test/default.c index a5de092..c695fea 100644 --- a/test/src/test/utils.c +++ b/test/src/test/default.c @@ -2,17 +2,15 @@ * ecgen, tool for generating Elliptic curve domain parameters * Copyright (C) 2017 J08nY */ -#include "utils.h" +#include "default.h" #include <criterion/criterion.h> #include <pari/pari.h> -static void *cr_simple_calloc(size_t size) { - return cr_calloc(1, size); -} + void default_setup(void) { pari_init(1000000, 1000000); - //set_mem_funcs(cr_malloc, cr_simple_calloc, cr_realloc, cr_free); + // set_mem_funcs(cr_malloc, cr_simple_calloc, cr_realloc, cr_free); } void default_teardown(void) { pari_close(); }
\ No newline at end of file diff --git a/test/src/test/utils.h b/test/src/test/default.h index 2780bd2..12ee4cb 100644 --- a/test/src/test/utils.h +++ b/test/src/test/default.h @@ -2,11 +2,11 @@ * ecgen, tool for generating Elliptic curve domain parameters * Copyright (C) 2017 J08nY */ -#ifndef ECGEN_UTILS_H -#define ECGEN_UTILS_H +#ifndef ECGEN_TEST_DEFAULT_H +#define ECGEN_TEST_DEFAULT_H void default_setup(void); void default_teardown(void); -#endif //ECGEN_UTILS_H +#endif // ECGEN_UTILS_H diff --git a/test/src/test/input.c b/test/src/test/input.c new file mode 100644 index 0000000..f171ca8 --- /dev/null +++ b/test/src/test/input.c @@ -0,0 +1,27 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#include "input.h" +#include "io/input.h" + +FILE *write_in; + +void input_setup(void) { + config_t cfg; + memset(&cfg, 0, sizeof(cfg)); + input_init(&cfg); + + int in_fd[2]; + pipe(in_fd); + + write_in = fdopen(in_fd[1], "w"); + setlinebuf(write_in); + in = fdopen(in_fd[0], "r"); + setlinebuf(in); +} + +void input_teardown(void) { + input_quit(); + fclose(write_in); +}
\ No newline at end of file diff --git a/test/src/test/input.h b/test/src/test/input.h new file mode 100644 index 0000000..5e57c01 --- /dev/null +++ b/test/src/test/input.h @@ -0,0 +1,16 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#ifndef ECGEN_TEST_INPUT_H +#define ECGEN_TEST_INPUT_H + +#include <stdio.h> + +extern FILE *write_in; + +void input_setup(void); + +void input_teardown(void); + +#endif // ECGEN_TEST_INPUT_H diff --git a/test/src/test/memory.c b/test/src/test/memory.c new file mode 100644 index 0000000..38c75c2 --- /dev/null +++ b/test/src/test/memory.c @@ -0,0 +1,17 @@ + +#include <string.h> +#include <criterion/alloc.h> +#include "memory.h" + +char *cr_strdup(const char *str) { + size_t len = strlen(str); + return cr_memdup(str, len + 1); +} + +void *cr_memdup(const void *str, size_t len) { + void *result = cr_malloc(len); + memcpy(result, str, len); + return result; +} + +void *cr_simple_calloc(size_t size) { return cr_calloc(1, size); }
\ No newline at end of file diff --git a/test/src/test/memory.h b/test/src/test/memory.h new file mode 100644 index 0000000..d97e3cc --- /dev/null +++ b/test/src/test/memory.h @@ -0,0 +1,13 @@ + +#ifndef ECGEN_TEST_MEMORY_H +#define ECGEN_TEST_MEMORY_H + +#include <stddef.h> + +char *cr_strdup(const char *str); + +void *cr_memdup(const void *str, size_t len); + +void *cr_simple_calloc(size_t size); + +#endif //ECGEN_TEST_MEMORY_H diff --git a/test/src/test/output.c b/test/src/test/output.c new file mode 100644 index 0000000..66c5809 --- /dev/null +++ b/test/src/test/output.c @@ -0,0 +1,49 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#include "output.h" +#include "misc/types.h" +#include "io/output.h" + +FILE *read_out = NULL; +FILE *read_err = NULL; +FILE *read_verbose = NULL; + +static void setup_stream(FILE **original_out, FILE **redirected_out) { + int fd[2]; + pipe(fd); + + *redirected_out = fdopen(fd[0], "r"); + setlinebuf(*redirected_out); + *original_out = fdopen(fd[1], "w"); + setlinebuf(*original_out); +} + +void output_setup(void) { + config_t cfg; + memset(&cfg, 0, sizeof(cfg)); + output_init(&cfg); + + int in_fd[2]; + pipe(in_fd); + + setup_stream(&out, &read_out); + setup_stream(&err, &read_err); + setup_stream(&verbose, &read_verbose); +} + +void output_teardown(void) { + if (read_out) { + fclose(out); + fclose(read_out); + } + if (read_err) { + fclose(err); + fclose(read_err); + } + if (read_verbose) { + fclose(verbose); + fclose(read_verbose); + } +} diff --git a/test/src/test/output.h b/test/src/test/output.h new file mode 100644 index 0000000..733cb5c --- /dev/null +++ b/test/src/test/output.h @@ -0,0 +1,18 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#ifndef ECGEN_TEST_OUTPUT_H +#define ECGEN_TEST_OUTPUT_H + +#include <stdio.h> + +extern FILE *read_out; +extern FILE *read_err; +extern FILE *read_verbose; + +void output_setup(void); + +void output_teardown(void); + +#endif // ECGEN_TEST_OUTPUT_H diff --git a/test/src/util/test_bits.c b/test/src/util/test_bits.c new file mode 100644 index 0000000..372541a --- /dev/null +++ b/test/src/util/test_bits.c @@ -0,0 +1,486 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ + +#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" + +TestSuite(bits, .init = default_setup, .fini = default_teardown); + +Test(bits, test_bits_new) { + bits_t *bits = bits_new(10); + cr_assert_not_null(bits, ); + cr_assert_eq(bits->bitlen, 10, ); + cr_assert_eq(bits->allocated, 2, ); + cr_assert_eq(bits->bits[0], 0, ); + cr_assert_eq(bits->bits[1], 0, ); + bits_free(&bits); +} + +Test(bits, test_bits_copy) { + bits_t *bits = bits_new(10); + bits->bits[0] = 0b10101010; + bits->bits[1] = 0b11000000; + + bits_t *other_bits = bits_copy(bits); + cr_assert_not_null(other_bits, ); + cr_assert_eq(other_bits->allocated, bits->allocated, ); + cr_assert_eq(other_bits->bitlen, bits->bitlen, ); + cr_assert_eq(other_bits->bits[0], bits->bits[0], ); + cr_assert_eq(other_bits->bits[1], bits->bits[1], ); + bits_free(&bits); + bits_free(&other_bits); +} + +Test(bits, test_bits_from_i) { + GEN i = int2n(5); + + bits_t *bits = bits_from_i(i); + cr_assert_not_null(bits, ); + cr_assert_eq(bits->bitlen, 6, ); + cr_assert_eq(bits->allocated, 1, ); + cr_assert_eq(bits->bits[0], 0b10000000, ); + bits_free(&bits); +} + +Test(bits, test_bits_from_hex) { + char *hex = "0ab"; + + bits_t *bits = bits_from_hex(hex); + cr_assert_not_null(bits, ); + cr_assert_eq(bits->bitlen, 12, ); + cr_assert_eq(bits->allocated, 2, ); + cr_assert_eq(bits->bits[0], 0x0a, ); + cr_assert_eq(bits->bits[1], 0xb0, ); + bits_free(&bits); +} + +Test(bits, test_bits_from_bin) { + char *bin = "000010101101"; + + bits_t *bits = bits_from_bin(bin); + cr_assert_not_null(bits, ); + cr_assert_eq(bits->bitlen, 12, ); + cr_assert_eq(bits->allocated, 2, ); + cr_assert_eq(bits->bits[0], 0b00001010, ); + cr_assert_eq(bits->bits[1], 0b11010000, ); + bits_free(&bits); +} + +Test(bits, test_bits_from_raw) { + unsigned char *raw = (unsigned char *)"\x0a\xb0"; + + bits_t *bits = bits_from_raw(raw, 16); + cr_assert_not_null(bits, ); + cr_assert_eq(bits->bitlen, 16, ); + cr_assert_eq(bits->allocated, 2, ); + cr_assert_eq(bits->bits[0], 0x0a, ); + cr_assert_eq(bits->bits[1], 0xb0, ); + bits_free(&bits); +} + +Test(bits, test_bits_from_bitvec) { + GEN bitvec = binary_zv(int2n(5)); + + bits_t *bits = bits_from_bitvec(bitvec); + cr_assert_not_null(bits, ); + cr_assert_eq(bits->bitlen, 6, ); + cr_assert_eq(bits->allocated, 1, ); + cr_assert_eq(bits->bits[0], 0b10000000, ); + bits_free(&bits); +} + +Test(bits, test_bits_to_i) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + GEN i = bits_to_i(bits); + cr_assert_not_null(bits, ); + cr_assert(gequal(i, int2n(5)), ); + bits_free(&bits); +} + +Test(bits, test_bits_to_hex) { + bits_t *bits = bits_new(12); + bits->bits[0] = 0xab; + bits->bits[1] = 0xc0; + + char *hex = bits_to_hex(bits); + cr_assert_not_null(hex, ); + cr_assert_str_eq(hex, "abc0", ); + try_free(hex); + bits_free(&bits); +} + +Test(bits, test_bits_to_bin) { + bits_t *bits = bits_new(12); + bits->bits[0] = 0b10101010; + bits->bits[1] = 0b11110000; + + char *bin = bits_to_bin(bits); + cr_assert_not_null(bin, ); + cr_assert_str_eq(bin, "101010101111", ); + try_free(bin); + bits_free(&bits); +} + +Test(bits, test_bits_to_raw) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + unsigned char *raw = bits_to_raw(bits); + size_t rawlen = bits_to_rawlen(bits); + cr_assert_not_null(raw, ); + cr_assert_eq(rawlen, 1, ); + cr_assert_eq(raw[0], 0b10000000, ); + try_free(raw); + bits_free(&bits); +} + +Test(bits, test_bits_to_bitvec) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + GEN bitvec = bits_to_bitvec(bits); + cr_assert_not_null(bitvec, ); + cr_assert(gequal(bitvec, binary_zv(int2n(5))), ); +} + +Test(bits, test_bits_concat) { + bits_t *one = bits_new(6); + one->bits[0] = 0b00000000; + + bits_t *other = bits_new(8); + other->bits[0] = 0b11001100; + + bits_t *cat = bits_concat(one, other, NULL); + cr_assert_not_null(cat, ); + cr_assert_eq(cat->bitlen, 14, ); + cr_assert_eq(cat->bits[0], 0b00000011, ); + cr_assert_eq(cat->bits[1], 0b00110000, ); + + bits_free(&one); + bits_free(&other); + bits_free(&cat); +} + +Test(bits, test_bits_or) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + bits_t *other_bits = bits_new(10); + other_bits->bits[0] = 0b00000000; + other_bits->bits[1] = 0b11000000; + + bits_t * or = bits_or(bits, other_bits); + cr_assert_not_null(or, ); + cr_assert_eq(or->bitlen, 10, ); + cr_assert_eq(or->bits[0], 0b00001000, ); + cr_assert_eq(or->bits[1], 0b11000000, ); + bits_free(&bits); + bits_free(&other_bits); + bits_free(& or); +} + +Test(bits, test_bits_and) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + bits_t *other_bits = bits_new(10); + other_bits->bits[0] = 0b00001000; + other_bits->bits[1] = 0b11000000; + + bits_t *and = bits_and(bits, other_bits); + cr_assert_not_null(and, ); + cr_assert_eq(and->bitlen, 10, ); + cr_assert_eq(and->bits[0], 0b00001000, ); + cr_assert_eq(and->bits[1], 0b00000000, ); + bits_free(&bits); + bits_free(&other_bits); + bits_free(&and); +} + +Test(bits, test_bits_notz) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + bits_notz(bits); + cr_assert_eq(bits->bitlen, 6, ); + cr_assert_eq(bits->bits[0], 0b01111100, ); + bits_free(&bits); +} + +Test(bits, test_bits_not) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + bits_t *not = bits_not(bits); + cr_assert_not_null(not, ); + cr_assert_eq(not->bitlen, 6, ); + cr_assert_eq(not->bits[0], 0b01111100, ); + bits_free(&bits); + bits_free(¬); +} + +Test(bits, test_bits_rotz) { + bits_t *bits = bits_new(10); + bits->bits[0] = 0b11111000; + bits->bits[1] = 0b00000000; + + bits_rotz(bits); + cr_assert_eq(bits->bitlen, 10, ); + cr_assert_eq(bits->bits[0], 0b00000111, ); + cr_assert_eq(bits->bits[1], 0b11000000, ); + bits_free(&bits); +} + +Test(bits, test_bits_rot) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + bits_t *rot = bits_rot(bits); + cr_assert_not_null(rot, ); + cr_assert_eq(rot->bitlen, 6, ); + cr_assert_eq(rot->bits[0], 0b00000100, ); + bits_free(&bits); + bits_free(&rot); + + bits = bits_new(5); + bits->bits[0] = 0b10100000; + + rot = bits_rot(bits); + cr_assert_not_null(rot, ); + cr_assert_eq(rot->bitlen, 5, ); + cr_assert_eq(rot->bits[0], 0b00101000, ); + bits_free(&bits); + bits_free(&rot); +} + +Test(bits, test_bits_shiftz) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10101000; + + bits_shiftz(bits, -1); + cr_assert_eq(bits->bitlen, 6, ); + cr_assert_eq(bits->bits[0], 0b01010100, ); + bits_free(&bits); +} + +Test(bits, test_bits_shift) { + bits_t *bits = bits_new(8); + bits->bits[0] = 0b11001100; + + bits_t *shift = bits_shift(bits, 2); + cr_assert_not_null(shift, ); + cr_assert_eq(shift->bitlen, 8, ); + cr_assert_eq(shift->bits[0], 0b00110000, ); + bits_free(&bits); + bits_free(&shift); +} + +Test(bits, test_bits_shiftrz) { + bits_t *bits = bits_new(8); + bits->bits[0] = 0b11001100; + + bits_shiftrz(bits, 1); + cr_assert_eq(bits->bitlen, 8, ); + cr_assert_eq(bits->bits[0], 0b10011001, ); + bits->bits[0] = 0b11001100; + + bits_shiftrz(bits, 9); + cr_assert_eq(bits->bitlen, 8, ); + cr_assert_eq(bits->bits[0], 0b10011001, ); + bits->bits[0] = 0b11001100; + + bits_shiftrz(bits, -10); + cr_assert_eq(bits->bitlen, 8, ); + cr_assert_eq(bits->bits[0], 0b00110011, ); + bits_free(&bits); +} + +Test(bits, test_bits_shiftr) { + bits_t *bits = bits_new(8); + bits->bits[0] = 0b11001100; + + bits_t *shift = bits_shiftr(bits, 1); + cr_assert_eq(shift->bitlen, 8, ); + cr_assert_eq(shift->bits[0], 0b10011001, ); + bits_free(&bits); + bits_free(&shift); +} + +Test(bits, test_bits_shiftiz) { + bits_t *bits = bits_new(8); + bits->bits[0] = 0b11001100; + + bits_shiftiz(bits, 2); + cr_assert_eq(bits->bitlen, 10, ); + cr_assert_eq(bits->bits[0], 0b11001100, ); + cr_assert_eq(bits->bits[1], 0b00000000, ); + + bits_shiftiz(bits, -2); + cr_assert_eq(bits->bitlen, 8, ); + cr_assert_eq(bits->bits[0], 0b11001100, ); + bits_free(&bits); +} + +Test(bits, test_bits_shitfi) { + bits_t *bits = bits_new(8); + bits->bits[0] = 0b11001100; + + bits_t *shift = bits_shifti(bits, -4); + cr_assert_eq(shift->bitlen, 4, ); + cr_assert_eq(shift->bits[0], 0b11000000, ); + bits_free(&bits); + bits_free(&shift); +} + +Test(bits, test_bits_lengthenz) { + bits_t *bits = bits_new(8); + bits->bits[0] = 0b11001100; + + bits_lengthenz(bits, 4); + cr_assert_eq(bits->bitlen, 12, ); + cr_assert_eq(bits->bits[0], 0b00001100, ); + cr_assert_eq(bits->bits[1], 0b11000000, ); + + bits_lengthenz(bits, -4); + cr_assert_eq(bits->bitlen, 16, ); + cr_assert_eq(bits->bits[0], 0b00001100, ); + cr_assert_eq(bits->bits[1], 0b11000000, ); + + bits_free(&bits); +} + +Test(bits, test_bits_lengthen) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b11111100; + + bits_t *longer = bits_lengthen(bits, 2); + cr_assert_not_null(longer, ); + cr_assert_eq(longer->bitlen, 8, ); + cr_assert_eq(longer->bits[0], 0b00111111, ); + bits_free(&bits); + bits_free(&longer); +} + +Test(bits, test_bits_shortenz) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10110100; + + bits_shortenz(bits, 2); + cr_assert_eq(bits->bitlen, 4, ); + cr_assert_eq(bits->bits[0], 0b11010000, ); + + bits_shortenz(bits, -2); + cr_assert_eq(bits->bitlen, 2, ); + cr_assert_eq(bits->bits[0], 0b11000000, ); + bits_free(&bits); +} + +Test(bits, test_bits_shorten) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10110100; + + bits_t *shorter = bits_shorten(bits, 4); + cr_assert_not_null(shorter, ); + cr_assert_eq(shorter->bitlen, 2, ); + cr_assert_eq(shorter->bits[0], 0b01000000, ); + bits_free(&bits); + bits_free(&shorter); +} + +struct sha1_params { + char *data; + unsigned char *hashout; +}; + +void sha1_params_cleanup(struct criterion_test_params *ctp) { + struct sha1_params *params = (struct sha1_params *)ctp->params; + cr_free(params->data); + cr_free(params->hashout); +} + +ParameterizedTestParameters(bits, test_bits_sha1) { + static struct sha1_params params[5] = {}; + params[0].data = cr_strdup("The quick brown fox jumps over the lazy dog"); + params[0].hashout = cr_memdup("\x2f\xd4\xe1\xc6\x7a\x2d\x28\xfc\xed\x84\x9e\xe1\xbb\x76\xe7\x39\x1b\x93\xeb\x12", 20); + params[1].data = cr_strdup("abc"); + params[1].hashout = cr_memdup("\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20); + params[2].data = cr_strdup(""); + params[2].hashout = cr_memdup("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09", 20); + params[3].data = cr_strdup("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + params[3].hashout = cr_memdup("\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1", 20); + params[4].data = cr_strdup("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + params[4].hashout = cr_memdup("\xa4\x9b\x24\x46\xa0\x2c\x64\x5b\xf4\x19\xf9\x95\xb6\x70\x91\x25\x3a\x04\xa2\x59", 20); + + size_t nb_params = sizeof(params) / sizeof(struct sha1_params); + return cr_make_param_array(struct sha1_params, params, nb_params, sha1_params_cleanup); +} + +ParameterizedTest(struct sha1_params *param, bits, test_bits_sha1) { + bits_t *bits = bits_from_raw((unsigned char *)param->data, strlen(param->data) * 8); + unsigned char hashout[20] = {}; + bits_sha1(bits, hashout); + + for (size_t i = 0; i < 20; ++i) { + cr_assert_eq(hashout[i], param->hashout[i], ); + } + + bits_free(&bits); +} + +Test(bits, test_bits_eq) { + bits_t *bits = bits_new(6); + bits->bits[0] = 0b10000000; + + bits_t *other_bits = bits_new(6); + other_bits->bits[0] = 0b10000000; + + cr_assert(bits_eq(bits, other_bits), ); + + bits->bits[0] = 0b10010000; + other_bits->bits[0] = 0b10000000; + + cr_assert_not(bits_eq(bits, other_bits), ); + + bits_free(&bits); + bits_free(&other_bits); +} + +Test(bits, test_bits_eq_len) { + bits_t *bits = bits_new(5); + bits->bits[0] = 0b10000000; + + bits_t *other_bits = bits_new(6); + other_bits->bits[0] = 0b10000000; + cr_assert_not(bits_eq(bits, other_bits), ); + bits_free(&bits); + bits_free(&other_bits); +} + +Test(bits, test_bits_eq_large) { + bits_t *bits = bits_new(10); + bits->bits[0] = 0b10000010; + bits->bits[1] = 0b11000000; + + bits_t *other_bits = bits_new(10); + other_bits->bits[0] = 0b10000010; + other_bits->bits[1] = 0b11000000; + + cr_assert(bits_eq(bits, other_bits), ); + + bits->bits[0] = 0b10000000; + other_bits->bits[0] = 0b00000010; + + cr_assert_not(bits_eq(bits, other_bits), ); + + bits_free(&bits); + bits_free(&other_bits); +} diff --git a/test/src/util/test_random.c b/test/src/util/test_random.c index 5e7f854..bb632a6 100644 --- a/test/src/util/test_random.c +++ b/test/src/util/test_random.c @@ -3,9 +3,9 @@ * Copyright (C) 2017 J08nY */ -#include "test/utils.h" -#include "util/random.h" #include <criterion/criterion.h> +#include "test/default.h" +#include "util/random.h" void random_setup() { default_setup(); @@ -17,18 +17,16 @@ TestSuite(random, .init = random_setup, .fini = default_teardown); Test(random, test_random_prime) { for (size_t i = 0; i < 100; ++i) { GEN p = random_prime(10); - cr_assert(isprime(p),); - cr_assert_lt(gcmp(p, int2n(10)), 0,); - cr_assert_gt(gcmp(p, int2n(9)), 0,); + cr_assert(isprime(p), ); + cr_assert_leq(cmpii(p, int2n(10)), 0, ); + cr_assert_geq(cmpii(p, int2n(9)), 0, ); } } Test(random, test_random_int) { for (size_t i = 0; i < 100; ++i) { GEN j = random_int(10); - cr_assert_lt(gcmp(j, int2n(10)), 0,); - cr_assert_gt(gcmp(j, int2n(9)), 0,); + cr_assert_leq(cmpii(j, int2n(10)), 0, ); + cr_assert_geq(cmpii(j, int2n(9)), 0, ); } } - - |
