aboutsummaryrefslogtreecommitdiff
path: root/src/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/io')
-rw-r--r--src/io/cli.c139
-rw-r--r--src/io/cli.h40
-rw-r--r--src/io/input.c115
-rw-r--r--src/io/input.h59
-rw-r--r--src/io/output.c76
-rw-r--r--src/io/output.h49
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