aboutsummaryrefslogtreecommitdiff
path: root/src/cli.c
blob: 88521c4dc5f7f1a86319c089ec5c8b845316ab2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * 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_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)."},
	// 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_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
				argp_failure(state, 1, 0,
				             "Invalid curve generation can not generate curves "
				             "from seed, random or prime order.");
			}
			break;
		case ARGP_KEY_NO_ARGS:
			argp_usage(state);
			break;
		default:
			return ARGP_ERR_UNKNOWN;
	}
	return 0;
}