diff options
author | jsing <> | 2018-02-08 11:17:44 +0000 |
---|---|---|
committer | jsing <> | 2018-02-08 11:17:44 +0000 |
commit | fc0438989e1c41cdad9328de2e6d0856c7e42063 (patch) | |
tree | 9b6b7eb8537d700c9622b9f248ac5a4b7f2392ad /src | |
parent | b887e277164c221b3385ae6f15eabe4c6a356c04 (diff) | |
download | openbsd-fc0438989e1c41cdad9328de2e6d0856c7e42063.tar.gz openbsd-fc0438989e1c41cdad9328de2e6d0856c7e42063.tar.bz2 openbsd-fc0438989e1c41cdad9328de2e6d0856c7e42063.zip |
Convert option handling for openssl(1) genpkey.
ok beck@ inoguchi@
Diffstat (limited to 'src')
-rw-r--r-- | src/usr.bin/openssl/genpkey.c | 287 |
1 files changed, 177 insertions, 110 deletions
diff --git a/src/usr.bin/openssl/genpkey.c b/src/usr.bin/openssl/genpkey.c index 9e8e08aef4..ef16a5e0da 100644 --- a/src/usr.bin/openssl/genpkey.c +++ b/src/usr.bin/openssl/genpkey.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: genpkey.c,v 1.11 2018/02/07 05:47:55 jsing Exp $ */ | 1 | /* $OpenBSD: genpkey.c,v 1.12 2018/02/08 11:17:44 jsing Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2006 | 3 | * project 2006 |
4 | */ | 4 | */ |
@@ -65,27 +65,165 @@ | |||
65 | #include <openssl/evp.h> | 65 | #include <openssl/evp.h> |
66 | #include <openssl/pem.h> | 66 | #include <openssl/pem.h> |
67 | 67 | ||
68 | static int | 68 | static int init_keygen_file(BIO * err, EVP_PKEY_CTX **pctx, const char *file); |
69 | init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, const char *file); | ||
70 | static int genpkey_cb(EVP_PKEY_CTX * ctx); | 69 | static int genpkey_cb(EVP_PKEY_CTX * ctx); |
71 | 70 | ||
71 | struct { | ||
72 | const EVP_CIPHER *cipher; | ||
73 | EVP_PKEY_CTX **ctx; | ||
74 | int do_param; | ||
75 | char *outfile; | ||
76 | int outformat; | ||
77 | char *passarg; | ||
78 | int text; | ||
79 | } genpkey_config; | ||
80 | |||
81 | static int | ||
82 | genpkey_opt_algorithm(char *arg) | ||
83 | { | ||
84 | if (!init_gen_str(bio_err, genpkey_config.ctx, arg, | ||
85 | genpkey_config.do_param)) | ||
86 | return (1); | ||
87 | |||
88 | return (0); | ||
89 | } | ||
90 | |||
91 | static int | ||
92 | genpkey_opt_cipher(int argc, char **argv, int *argsused) | ||
93 | { | ||
94 | char *name = argv[0]; | ||
95 | |||
96 | if (*name++ != '-') | ||
97 | return (1); | ||
98 | |||
99 | if (genpkey_config.do_param == 1) | ||
100 | return (1); | ||
101 | |||
102 | if (strcmp(name, "none") == 0) { | ||
103 | genpkey_config.cipher = NULL; | ||
104 | *argsused = 1; | ||
105 | return (0); | ||
106 | } | ||
107 | |||
108 | if ((genpkey_config.cipher = EVP_get_cipherbyname(name)) != NULL) { | ||
109 | *argsused = 1; | ||
110 | return (0); | ||
111 | } | ||
112 | |||
113 | return (1); | ||
114 | } | ||
115 | |||
116 | static int | ||
117 | genpkey_opt_paramfile(char *arg) | ||
118 | { | ||
119 | if (genpkey_config.do_param == 1) | ||
120 | return (1); | ||
121 | if (!init_keygen_file(bio_err, genpkey_config.ctx, arg)) | ||
122 | return (1); | ||
123 | |||
124 | return (0); | ||
125 | } | ||
126 | |||
127 | static int | ||
128 | genpkey_opt_pkeyopt(char *arg) | ||
129 | { | ||
130 | if (*genpkey_config.ctx == NULL) { | ||
131 | BIO_puts(bio_err, "No keytype specified\n"); | ||
132 | return (1); | ||
133 | } | ||
134 | |||
135 | if (pkey_ctrl_string(*genpkey_config.ctx, arg) <= 0) { | ||
136 | BIO_puts(bio_err, "parameter setting error\n"); | ||
137 | ERR_print_errors(bio_err); | ||
138 | return (1); | ||
139 | } | ||
140 | |||
141 | return (0); | ||
142 | } | ||
143 | |||
144 | struct option genpkey_options[] = { | ||
145 | { | ||
146 | .name = "algorithm", | ||
147 | .argname = "name", | ||
148 | .desc = "Public key algorithm to use (must precede -pkeyopt)", | ||
149 | .type = OPTION_ARG_FUNC, | ||
150 | .opt.argfunc = genpkey_opt_algorithm, | ||
151 | }, | ||
152 | { | ||
153 | .name = "genparam", | ||
154 | .desc = "Generate a set of parameters instead of a private key", | ||
155 | .type = OPTION_FLAG, | ||
156 | .opt.flag = &genpkey_config.do_param, | ||
157 | }, | ||
158 | { | ||
159 | .name = "out", | ||
160 | .argname = "file", | ||
161 | .desc = "Output file to write to (default stdout)", | ||
162 | .type = OPTION_ARG, | ||
163 | .opt.arg = &genpkey_config.outfile, | ||
164 | }, | ||
165 | { | ||
166 | .name = "outform", | ||
167 | .argname = "format", | ||
168 | .desc = "Output format (DER or PEM)", | ||
169 | .type = OPTION_ARG_FORMAT, | ||
170 | .opt.value = &genpkey_config.outformat, | ||
171 | }, | ||
172 | { | ||
173 | .name = "paramfile", | ||
174 | .argname = "file", | ||
175 | .desc = "File to load public key algorithm parameters from\n" | ||
176 | "(must precede -pkeyopt)", | ||
177 | .type = OPTION_ARG_FUNC, | ||
178 | .opt.argfunc = genpkey_opt_paramfile, | ||
179 | }, | ||
180 | { | ||
181 | .name = "pass", | ||
182 | .argname = "arg", | ||
183 | .desc = "Output file password source", | ||
184 | .type = OPTION_ARG, | ||
185 | .opt.arg = &genpkey_config.passarg, | ||
186 | }, | ||
187 | { | ||
188 | .name = "pkeyopt", | ||
189 | .argname = "opt:value", | ||
190 | .desc = "Set public key algorithm option to the given value", | ||
191 | .type = OPTION_ARG_FUNC, | ||
192 | .opt.argfunc = genpkey_opt_pkeyopt, | ||
193 | }, | ||
194 | { | ||
195 | .name = "text", | ||
196 | .desc = "Print the private/public key in human readable form", | ||
197 | .type = OPTION_FLAG, | ||
198 | .opt.flag = &genpkey_config.text, | ||
199 | }, | ||
200 | { | ||
201 | .name = NULL, | ||
202 | .type = OPTION_ARGV_FUNC, | ||
203 | .opt.argvfunc = genpkey_opt_cipher, | ||
204 | }, | ||
205 | {NULL}, | ||
206 | }; | ||
207 | |||
208 | static void | ||
209 | genpkey_usage() | ||
210 | { | ||
211 | fprintf(stderr, | ||
212 | "usage: genpkey [-algorithm alg] [cipher] [-genparam] [-out file]\n" | ||
213 | " [-outform der | pem] [-paramfile file] [-pass arg]\n" | ||
214 | " [-pkeyopt opt:value] [-text]\n\n"); | ||
215 | options_usage(genpkey_options); | ||
216 | } | ||
217 | |||
72 | int | 218 | int |
73 | genpkey_main(int argc, char **argv) | 219 | genpkey_main(int argc, char **argv) |
74 | { | 220 | { |
75 | char **args, *outfile = NULL; | ||
76 | char *passarg = NULL; | ||
77 | BIO *in = NULL, *out = NULL; | 221 | BIO *in = NULL, *out = NULL; |
78 | const EVP_CIPHER *cipher = NULL; | ||
79 | int outformat; | ||
80 | int text = 0; | ||
81 | EVP_PKEY *pkey = NULL; | ||
82 | EVP_PKEY_CTX *ctx = NULL; | 222 | EVP_PKEY_CTX *ctx = NULL; |
223 | EVP_PKEY *pkey = NULL; | ||
83 | char *pass = NULL; | 224 | char *pass = NULL; |
84 | int badarg = 0; | ||
85 | int ret = 1, rv; | 225 | int ret = 1, rv; |
86 | 226 | ||
87 | int do_param = 0; | ||
88 | |||
89 | if (single_execution) { | 227 | if (single_execution) { |
90 | if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { | 228 | if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { |
91 | perror("pledge"); | 229 | perror("pledge"); |
@@ -93,98 +231,29 @@ genpkey_main(int argc, char **argv) | |||
93 | } | 231 | } |
94 | } | 232 | } |
95 | 233 | ||
96 | outformat = FORMAT_PEM; | 234 | memset(&genpkey_config, 0, sizeof(genpkey_config)); |
97 | 235 | genpkey_config.ctx = &ctx; | |
98 | args = argv + 1; | 236 | genpkey_config.outformat = FORMAT_PEM; |
99 | while (!badarg && *args && *args[0] == '-') { | 237 | |
100 | if (!strcmp(*args, "-outform")) { | 238 | if (options_parse(argc, argv, genpkey_options, NULL, NULL) != 0) { |
101 | if (args[1]) { | 239 | genpkey_usage(); |
102 | args++; | 240 | goto end; |
103 | outformat = str2fmt(*args); | ||
104 | } else | ||
105 | badarg = 1; | ||
106 | } else if (!strcmp(*args, "-pass")) { | ||
107 | if (!args[1]) | ||
108 | goto bad; | ||
109 | passarg = *(++args); | ||
110 | } | ||
111 | else if (!strcmp(*args, "-paramfile")) { | ||
112 | if (!args[1]) | ||
113 | goto bad; | ||
114 | args++; | ||
115 | if (do_param == 1) | ||
116 | goto bad; | ||
117 | if (!init_keygen_file(bio_err, &ctx, *args)) | ||
118 | goto end; | ||
119 | } else if (!strcmp(*args, "-out")) { | ||
120 | if (args[1]) { | ||
121 | args++; | ||
122 | outfile = *args; | ||
123 | } else | ||
124 | badarg = 1; | ||
125 | } else if (strcmp(*args, "-algorithm") == 0) { | ||
126 | if (!args[1]) | ||
127 | goto bad; | ||
128 | if (!init_gen_str(bio_err, &ctx, *(++args), do_param)) | ||
129 | goto end; | ||
130 | } else if (strcmp(*args, "-pkeyopt") == 0) { | ||
131 | if (!args[1]) | ||
132 | goto bad; | ||
133 | if (!ctx) { | ||
134 | BIO_puts(bio_err, "No keytype specified\n"); | ||
135 | goto bad; | ||
136 | } else if (pkey_ctrl_string(ctx, *(++args)) <= 0) { | ||
137 | BIO_puts(bio_err, "parameter setting error\n"); | ||
138 | ERR_print_errors(bio_err); | ||
139 | goto end; | ||
140 | } | ||
141 | } else if (strcmp(*args, "-genparam") == 0) { | ||
142 | if (ctx) | ||
143 | goto bad; | ||
144 | do_param = 1; | ||
145 | } else if (strcmp(*args, "-text") == 0) | ||
146 | text = 1; | ||
147 | else { | ||
148 | cipher = EVP_get_cipherbyname(*args + 1); | ||
149 | if (!cipher) { | ||
150 | BIO_printf(bio_err, "Unknown cipher %s\n", | ||
151 | *args + 1); | ||
152 | badarg = 1; | ||
153 | } | ||
154 | if (do_param == 1) | ||
155 | badarg = 1; | ||
156 | } | ||
157 | args++; | ||
158 | } | 241 | } |
159 | 242 | ||
160 | if (!ctx) | 243 | if (ctx == NULL) { |
161 | badarg = 1; | 244 | genpkey_usage(); |
162 | |||
163 | if (badarg) { | ||
164 | bad: | ||
165 | BIO_printf(bio_err, "Usage: genpkey [options]\n"); | ||
166 | BIO_printf(bio_err, "where options may be\n"); | ||
167 | BIO_printf(bio_err, "-out file output file\n"); | ||
168 | BIO_printf(bio_err, "-outform X output format (DER or PEM)\n"); | ||
169 | BIO_printf(bio_err, "-pass arg output file pass phrase source\n"); | ||
170 | BIO_printf(bio_err, "-<cipher> use cipher <cipher> to encrypt the key\n"); | ||
171 | BIO_printf(bio_err, "-paramfile file parameters file\n"); | ||
172 | BIO_printf(bio_err, "-algorithm alg the public key algorithm\n"); | ||
173 | BIO_printf(bio_err, "-pkeyopt opt:value set the public key algorithm option <opt>\n" | ||
174 | " to value <value>\n"); | ||
175 | BIO_printf(bio_err, "-genparam generate parameters, not key\n"); | ||
176 | BIO_printf(bio_err, "-text print the in text\n"); | ||
177 | BIO_printf(bio_err, "NB: options order may be important! See the manual page.\n"); | ||
178 | goto end; | 245 | goto end; |
179 | } | 246 | } |
180 | if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { | 247 | |
248 | if (!app_passwd(bio_err, genpkey_config.passarg, NULL, &pass, NULL)) { | ||
181 | BIO_puts(bio_err, "Error getting password\n"); | 249 | BIO_puts(bio_err, "Error getting password\n"); |
182 | goto end; | 250 | goto end; |
183 | } | 251 | } |
184 | if (outfile) { | 252 | if (genpkey_config.outfile != NULL) { |
185 | if (!(out = BIO_new_file(outfile, "wb"))) { | 253 | if ((out = BIO_new_file(genpkey_config.outfile, "wb")) == |
186 | BIO_printf(bio_err, | 254 | NULL) { |
187 | "Can't open output file %s\n", outfile); | 255 | BIO_printf(bio_err, "Can't open output file %s\n", |
256 | genpkey_config.outfile); | ||
188 | goto end; | 257 | goto end; |
189 | } | 258 | } |
190 | } else { | 259 | } else { |
@@ -194,7 +263,7 @@ genpkey_main(int argc, char **argv) | |||
194 | EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); | 263 | EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); |
195 | EVP_PKEY_CTX_set_app_data(ctx, bio_err); | 264 | EVP_PKEY_CTX_set_app_data(ctx, bio_err); |
196 | 265 | ||
197 | if (do_param) { | 266 | if (genpkey_config.do_param) { |
198 | if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { | 267 | if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { |
199 | BIO_puts(bio_err, "Error generating parameters\n"); | 268 | BIO_puts(bio_err, "Error generating parameters\n"); |
200 | ERR_print_errors(bio_err); | 269 | ERR_print_errors(bio_err); |
@@ -208,12 +277,12 @@ genpkey_main(int argc, char **argv) | |||
208 | } | 277 | } |
209 | } | 278 | } |
210 | 279 | ||
211 | if (do_param) | 280 | if (genpkey_config.do_param) |
212 | rv = PEM_write_bio_Parameters(out, pkey); | 281 | rv = PEM_write_bio_Parameters(out, pkey); |
213 | else if (outformat == FORMAT_PEM) | 282 | else if (genpkey_config.outformat == FORMAT_PEM) |
214 | rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, | 283 | rv = PEM_write_bio_PrivateKey(out, pkey, genpkey_config.cipher, |
215 | NULL, pass); | 284 | NULL, 0, NULL, pass); |
216 | else if (outformat == FORMAT_ASN1) | 285 | else if (genpkey_config.outformat == FORMAT_ASN1) |
217 | rv = i2d_PrivateKey_bio(out, pkey); | 286 | rv = i2d_PrivateKey_bio(out, pkey); |
218 | else { | 287 | else { |
219 | BIO_printf(bio_err, "Bad format specified for key\n"); | 288 | BIO_printf(bio_err, "Bad format specified for key\n"); |
@@ -224,8 +293,8 @@ genpkey_main(int argc, char **argv) | |||
224 | BIO_puts(bio_err, "Error writing key\n"); | 293 | BIO_puts(bio_err, "Error writing key\n"); |
225 | ERR_print_errors(bio_err); | 294 | ERR_print_errors(bio_err); |
226 | } | 295 | } |
227 | if (text) { | 296 | if (genpkey_config.text) { |
228 | if (do_param) | 297 | if (genpkey_config.do_param) |
229 | rv = EVP_PKEY_print_params(out, pkey, 0, NULL); | 298 | rv = EVP_PKEY_print_params(out, pkey, 0, NULL); |
230 | else | 299 | else |
231 | rv = EVP_PKEY_print_private(out, pkey, 0, NULL); | 300 | rv = EVP_PKEY_print_private(out, pkey, 0, NULL); |
@@ -248,8 +317,7 @@ genpkey_main(int argc, char **argv) | |||
248 | } | 317 | } |
249 | 318 | ||
250 | static int | 319 | static int |
251 | init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, | 320 | init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, const char *file) |
252 | const char *file) | ||
253 | { | 321 | { |
254 | BIO *pbio; | 322 | BIO *pbio; |
255 | EVP_PKEY *pkey = NULL; | 323 | EVP_PKEY *pkey = NULL; |
@@ -289,11 +357,10 @@ init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, | |||
289 | } | 357 | } |
290 | 358 | ||
291 | int | 359 | int |
292 | init_gen_str(BIO * err, EVP_PKEY_CTX ** pctx, | 360 | init_gen_str(BIO * err, EVP_PKEY_CTX ** pctx, const char *algname, int do_param) |
293 | const char *algname, int do_param) | ||
294 | { | 361 | { |
295 | EVP_PKEY_CTX *ctx = NULL; | ||
296 | const EVP_PKEY_ASN1_METHOD *ameth; | 362 | const EVP_PKEY_ASN1_METHOD *ameth; |
363 | EVP_PKEY_CTX *ctx = NULL; | ||
297 | int pkey_id; | 364 | int pkey_id; |
298 | 365 | ||
299 | if (*pctx) { | 366 | if (*pctx) { |