diff options
Diffstat (limited to 'src/io')
| -rw-r--r-- | src/io/cli.c | 139 | ||||
| -rw-r--r-- | src/io/cli.h | 40 | ||||
| -rw-r--r-- | src/io/input.c | 115 | ||||
| -rw-r--r-- | src/io/input.h | 59 | ||||
| -rw-r--r-- | src/io/output.c | 76 | ||||
| -rw-r--r-- | src/io/output.h | 49 |
6 files changed, 478 insertions, 0 deletions
diff --git a/src/io/cli.c b/src/io/cli.c new file mode 100644 index 0000000..12ceabd --- /dev/null +++ b/src/io/cli.c @@ -0,0 +1,139 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#include "cli.h" +#include <string.h> + +char doc[] = + "ecgen, tool for generating Elliptic curve domain parameters.\v(C) 2017 " + "Eastern Seaboard Phishing Authority"; +char args_doc[] = "bits"; + +enum opt_keys { + OPT_DATADIR = 'd', + OPT_PRIME = 'p', + OPT_RANDOM = 'r', + OPT_SEED = 's', + OPT_INVALID = 'i', + OPT_ORDER = 'n', + OPT_KOBLITZ = 'k', + OPT_OUTPUT = 'o', + OPT_INPUT = 'f', + OPT_APPEND = 'a', + OPT_FP = 1, + OPT_F2M = 2, +}; + +// clang-format off +struct argp_option options[] = { + // Field specification + {"fp", OPT_FP, 0, 0, "Prime field."}, + {"f2m", OPT_F2M, 0, 0, "Binary field."}, + // Curve specification + {"random", OPT_RANDOM, 0, 0, "Generate a random curve."}, + {"prime", OPT_PRIME, 0, 0, "Generate a curve with prime order."}, + {"seed", OPT_SEED, "SEED", OPTION_ARG_OPTIONAL, "Generate a curve from SEED (ANSI X9.62 verifiable procedure)."}, + {"invalid", OPT_INVALID, 0, 0, "Generate a set of invalid curves (for a given curve)."}, + {"order", OPT_ORDER, "ORDER", 0, "Generate a curve with given order (using Complex Multiplication)."}, + {"koblitz", OPT_KOBLITZ, 0, 0, "Generate a Koblitz curve."}, + // Other + {"data-dir", OPT_DATADIR, "DIR", 0, "PARI/GP data directory (containing seadata package)."}, + {"input", OPT_INPUT, "FILE", 0, "Input from file."}, + {"output", OPT_OUTPUT, "FILE", 0, "Output into file. Overwrites any existing file!"}, + {"append", OPT_APPEND, 0, 0, "Append to output file (don't overwrite)."}, + {0}}; +// clang-format on + +error_t parse_opt(int key, char *arg, struct argp_state *state) { + struct config_t *cfg = state->input; + + switch (key) { + case OPT_DATADIR: + cfg->datadir = arg; + break; + case OPT_INPUT: + cfg->input = arg; + break; + case OPT_OUTPUT: + cfg->output = arg; + break; + case OPT_APPEND: + cfg->append = true; + break; + case OPT_RANDOM: + cfg->random = true; + break; + case OPT_PRIME: + cfg->prime = true; + break; + case OPT_INVALID: + cfg->invalid = true; + break; + case OPT_ORDER: + cfg->cm = true; + if (arg) { + cfg->order = arg; + } + break; + case OPT_KOBLITZ: + cfg->koblitz = true; + break; + case OPT_SEED: + cfg->from_seed = true; + if (arg) { + // ANSI X9.62 specifies seed as at least 160 bits in length. + if (strlen(arg) < 20) { + argp_failure( + state, 1, 0, + "SEED must be at least 160 bits(20 characters)."); + } + cfg->seed = arg; + } + break; + case OPT_FP: + cfg->field = FIELD_PRIME; + cfg->prime_field = true; + break; + case OPT_F2M: + cfg->field = FIELD_BINARY; + cfg->binary_field = true; + break; + case ARGP_KEY_ARG: + if (state->arg_num >= 1) { + argp_usage(state); + } + + cfg->bits = strtol(arg, NULL, 10); + break; + case ARGP_KEY_END: + // validate all option states here. + // Only one field + if (!cfg->prime_field && !cfg->binary_field) { + argp_failure(state, 1, 0, + "Specify field type, prime or binary, with --fp / " + "--f2m(but not both)."); + } + // Invalid is not prime or seed or random by definition. + if (cfg->invalid && (cfg->prime || cfg->from_seed || cfg->random)) { + // not seed, not prime, not random + argp_failure(state, 1, 0, + "Invalid curve generation can not generate curves " + "from seed, random or prime order."); + } + if (cfg->cm && (cfg->prime || cfg->from_seed || cfg->invalid)) { + argp_failure(state, 1, 0, + "Fixed order curve generation can not generate " + "curves from seed, or invalid curves. Prime order " + "also doesn't make sense if the given one isn't " + "prime."); + } + break; + case ARGP_KEY_NO_ARGS: + argp_usage(state); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} diff --git a/src/io/cli.h b/src/io/cli.h new file mode 100644 index 0000000..0826419 --- /dev/null +++ b/src/io/cli.h @@ -0,0 +1,40 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#ifndef ECGEN_CLI_H +#define ECGEN_CLI_H + +#include <argp.h> +#include <stdbool.h> +#include <stdlib.h> + +extern char doc[]; +extern char args_doc[]; +extern struct argp_option options[]; + +enum field_e { FIELD_PRIME, FIELD_BINARY }; + +typedef struct config_t { + enum field_e field; + bool binary_field; + bool prime_field; + bool random; + bool prime; + bool invalid; + bool cm; + char *order; + bool koblitz; + bool from_seed; + char *seed; + char *datadir; + char *output; + char *input; + bool append; + long bits; + +} config_t; + +error_t parse_opt(int key, char *arg, struct argp_state *state); + +#endif // ECGEN_CLI_H diff --git a/src/io/input.c b/src/io/input.c new file mode 100644 index 0000000..3dcca00 --- /dev/null +++ b/src/io/input.c @@ -0,0 +1,115 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#include <parson/parson.h> +#include "input.h" + +FILE *in; + +GEN fread_i(FILE *stream, const char *prompt, long bits, int delim) { + if (prompt) { + printf("%s ", prompt); + } + char *line = NULL; + size_t n = 0; + + ssize_t len = getdelim(&line, &n, delim, stream); + if (len == 1) { + free(line); + return gen_m1; + } + pari_sp ltop = avma; + GEN in = strtoi(line); + free(line); + + // check bitsize here + GEN size = int2n(bits); + if (cmpii(in, size)) { + return gerepileupto(ltop, in); + } else { + fprintf(stderr, "Number too big(> %ld bits).\n", bits); + return gen_m1; + } +} + +GEN fread_prime(FILE *stream, const char *prompt, long bits, int delim) { + GEN read = fread_i(stream, prompt, bits, delim); + if (equalii(read, gen_m1)) { + return read; + } else { + if (isprime(read)) { + return read; + } else { + fprintf(stderr, "Number is not prime. Prime required.\n"); + return gen_m1; + } + } +} + +GEN fread_int(FILE *stream, const char *prompt, long bits, int delim) { + return fread_i(stream, prompt, bits, delim); +} + +GEN fread_short(FILE *stream, const char *prompt, int delim) { + return fread_i(stream, prompt, 16, delim); +} + +GEN fread_string(FILE *stream, const char *prompt, int delim) { + if (prompt) { + printf("%s ", prompt); + } + char *line = NULL; + size_t n = 0; + + ssize_t len = getdelim(&line, &n, delim, stream); + if (len == 1) { + free(line); + return strtoGENstr(""); + } + + line[len - 1] = 0; + GEN result = strtoGENstr(line); + free(line); + return result; +} + +GEN fread_param(param_t param, FILE *stream, const char *prompt, long bits, + int delim) { + switch (param) { + case PARAM_PRIME: + return fread_prime(stream, prompt, bits, delim); + case PARAM_INT: + return fread_int(stream, prompt, bits, delim); + case PARAM_SHORT: + return fread_short(stream, prompt, delim); + case PARAM_STRING: + return fread_string(stream, prompt, delim); + } + return gen_m1; +} + +GEN read_param(param_t param, const char *prompt, long bits, int delim) { + return fread_param(param, stdin, prompt, bits, delim); +} + +FILE *input_open(const char *input) { + json_set_allocation_functions(pari_malloc, pari_free); + if (input) { + FILE *in = fopen(input, "r"); + if (!in) { + // fallback to stdin or quit? + in = stdin; + perror("Failed to open input file."); + } + return in; + } else { + return stdin; + } +} + +void input_close(FILE *in) { + if (in != NULL && in != stdout) { + fclose(in); + } +} diff --git a/src/io/input.h b/src/io/input.h new file mode 100644 index 0000000..f403661 --- /dev/null +++ b/src/io/input.h @@ -0,0 +1,59 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#ifndef ECGEN_INPUT_H +#define ECGEN_INPUT_H + +#include "math/random.h" + +typedef enum PARAM { + PARAM_PRIME, + PARAM_INT, + PARAM_SHORT, + PARAM_STRING +} param_t; + +/** + * + * @param stream + * @param prompt + * @param bits + * @param delim + * @return + */ +GEN fread_prime(FILE *stream, const char *prompt, long bits, int delim); + +/** + * + * @param stream + * @param prompt + * @param bits + * @param delim + * @return + */ +GEN fread_int(FILE *stream, const char *prompt, long bits, int delim); + +/** + * + * @param stream + * @param prompt + * @param delim + * @return + */ +GEN fread_short(FILE *stream, const char *prompt, int delim); + +GEN fread_string(FILE *stream, const char *prompt, int delim); + +GEN fread_param(param_t param, FILE *stream, const char *prompt, long bits, + int delim); + +GEN read_param(param_t param, const char *prompt, long bits, int delim); + +extern FILE *in; + +FILE *input_open(const char *input); + +void input_close(FILE *in); + +#endif // ECGEN_INPUT_H diff --git a/src/io/output.c b/src/io/output.c new file mode 100644 index 0000000..86de015 --- /dev/null +++ b/src/io/output.c @@ -0,0 +1,76 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ + +#include "output.h" +#include <parson/parson.h> + +FILE *out; + +char *output_scsv(const char *format, char delim, GEN vector) { + long len = lg(vector) - 1; + char *params[len]; + size_t lengths[len]; + size_t total = 0; + for (long i = 0; i < len; ++i) { + params[i] = pari_sprintf(format, gel(vector, i + 1)); + lengths[i] = strlen(params[i]); + total += lengths[i]; + } + + char *result = (char *)malloc(total + len); + if (!result) { + perror("Couldn't malloc."); + exit(1); + } + + size_t offset = 0; + for (long i = 0; i < len; ++i) { + memcpy(result + offset, params[i], lengths[i]); + free(params[i]); + + offset += lengths[i]; + if (i != len - 1) { + result[offset] = delim; + offset++; + } + } + memset(result + offset, 0, 1); + + return result; +} + +void output_csv(FILE *out, const char *format, char delim, GEN vector) { + char *string = output_scsv(format, delim, vector); + fprintf(out, "%s", string); + free(string); +} + +char *output_sjson(GEN vector) { + parson +} + +void output_json(FILE *out, GEN vector) {} + +FILE *output_open(const char *output, bool append) { + json_set_allocation_functions(pari_malloc, pari_free); + + if (output) { + FILE *out = fopen(output, append ? "a" : "w"); + if (!out) { + // fallback to stdout and output err + out = stdout; + perror("Failed to open output file."); + } + return out; + } else { + return stdout; + } +} + +void output_close(FILE *out) { + if (out != NULL && out != stdout) { + fclose(out); + } +}
\ No newline at end of file diff --git a/src/io/output.h b/src/io/output.h new file mode 100644 index 0000000..99b92b7 --- /dev/null +++ b/src/io/output.h @@ -0,0 +1,49 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#ifndef ECGEN_OUTPUT_H +#define ECGEN_OUTPUT_H + +#include <pari/pari.h> +#include <stdbool.h> + +/** + * + * @param delim + * @param format + * @param vector + * @return + */ +char *output_scsv(const char *format, char delim, GEN vector); + +/** + * + * @param out + * @param delim + * @param format + * @param vector + */ +void output_csv(FILE *out, const char *format, char delim, GEN vector); + +/** + * + * @param vector + * @return + */ +char *output_sjson(GEN vector); + +/** + * + * @param out + * @param vector + */ +void output_json(FILE *out, GEN vector); + +extern FILE *out; + +FILE *output_open(const char *output, bool append); + +void output_close(FILE *out); + +#endif // ECGEN_OUTPUT_H |
