summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/usr.bin/openssl/ec.c417
1 files changed, 247 insertions, 170 deletions
diff --git a/src/usr.bin/openssl/ec.c b/src/usr.bin/openssl/ec.c
index 063e57c818..16daf3fa13 100644
--- a/src/usr.bin/openssl/ec.c
+++ b/src/usr.bin/openssl/ec.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec.c,v 1.2 2014/08/28 14:23:52 jsing Exp $ */ 1/* $OpenBSD: ec.c,v 1.3 2015/07/12 22:16:49 doug Exp $ */
2/* 2/*
3 * Written by Nils Larsch for the OpenSSL project. 3 * Written by Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -60,6 +60,7 @@
60 60
61#ifndef OPENSSL_NO_EC 61#ifndef OPENSSL_NO_EC
62 62
63#include <ctype.h>
63#include <stdio.h> 64#include <stdio.h>
64#include <stdlib.h> 65#include <stdlib.h>
65#include <string.h> 66#include <string.h>
@@ -71,16 +72,212 @@
71#include <openssl/evp.h> 72#include <openssl/evp.h>
72#include <openssl/pem.h> 73#include <openssl/pem.h>
73 74
74/* -inform arg - input format - default PEM (one of DER, NET or PEM) 75static struct {
75 * -outform arg - output format - default PEM 76 int asn1_flag;
76 * -in arg - input file - default stdin 77 const EVP_CIPHER *enc;
77 * -out arg - output file - default stdout 78#ifndef OPENSSL_NO_ENGINE
78 * -des - encrypt output if PEM format with DES in cbc mode 79 char *engine;
79 * -text - print a text version 80#endif
80 * -param_out - print the elliptic curve parameters 81 point_conversion_form_t form;
81 * -conv_form arg - specifies the point encoding form 82 char *infile;
82 * -param_enc arg - specifies the parameter encoding 83 int informat;
83 */ 84 char *outfile;
85 int outformat;
86 int new_asn1_flag;
87 int new_form;
88 int noout;
89 int param_out;
90 char *passargin;
91 char *passargout;
92 int pubin;
93 int pubout;
94 int text;
95} ec_config;
96
97static int
98ec_opt_enc(int argc, char **argv, int *argsused)
99{
100 char *name = argv[0];
101
102 if (*name++ != '-')
103 return (1);
104
105 if ((ec_config.enc = EVP_get_cipherbyname(name)) != NULL) {
106 *argsused = 1;
107 return (0);
108 }
109
110 return (1);
111}
112
113static int
114ec_opt_form(char *arg)
115{
116 if (strcmp(arg, "compressed") == 0)
117 ec_config.form = POINT_CONVERSION_COMPRESSED;
118 else if (strcmp(arg, "uncompressed") == 0)
119 ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
120 else if (strcmp(arg, "hybrid") == 0)
121 ec_config.form = POINT_CONVERSION_HYBRID;
122 else {
123 fprintf(stderr, "Invalid point conversion: %s\n", arg);
124 return (1);
125 }
126
127 ec_config.new_form = 1;
128 return (0);
129}
130
131static int
132ec_opt_named(char *arg)
133{
134 if (strcmp(arg, "named_curve") == 0)
135 ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
136 else if (strcmp(arg, "explicit") == 0)
137 ec_config.asn1_flag = 0;
138 else {
139 fprintf(stderr, "Invalid curve type: %s\n", arg);
140 return (1);
141 }
142
143 ec_config.new_asn1_flag = 1;
144 return (0);
145}
146
147static struct option ec_options[] = {
148 {
149 .name = "conv_form",
150 .argname = "form",
151 .desc = "Specify the point conversion form (default"
152 " \"named_curve\")",
153 .type = OPTION_ARG_FUNC,
154 .opt.argfunc = ec_opt_form,
155 },
156#ifndef OPENSSL_NO_ENGINE
157 {
158 .name = "engine",
159 .argname = "id",
160 .desc = "Use the engine specified by the given identifier",
161 .type = OPTION_ARG,
162 .opt.arg = &ec_config.engine,
163 },
164#endif
165 {
166 .name = "in",
167 .argname = "file",
168 .desc = "Input file (default stdin)",
169 .type = OPTION_ARG,
170 .opt.arg = &ec_config.infile,
171 },
172 {
173 .name = "inform",
174 .argname = "format",
175 .desc = "Input format (DER or PEM (default))",
176 .type = OPTION_ARG_FORMAT,
177 .opt.value = &ec_config.informat,
178 },
179 {
180 .name = "noout",
181 .desc = "No output",
182 .type = OPTION_FLAG,
183 .opt.flag = &ec_config.noout,
184 },
185 {
186 .name = "out",
187 .argname = "file",
188 .desc = "Output file (default stdout)",
189 .type = OPTION_ARG,
190 .opt.arg = &ec_config.outfile,
191 },
192 {
193 .name = "outform",
194 .argname = "format",
195 .desc = "Output format (DER or PEM (default))",
196 .type = OPTION_ARG_FORMAT,
197 .opt.value = &ec_config.outformat,
198 },
199 {
200 .name = "param_enc",
201 .argname = "type",
202 .desc = "Specify the way the ec parameters are encoded"
203 " (default \"uncompressed\")",
204 .type = OPTION_ARG_FUNC,
205 .opt.argfunc = ec_opt_named,
206 },
207 {
208 .name = "param_out",
209 .desc = "Print the elliptic curve parameters",
210 .type = OPTION_FLAG,
211 .opt.flag = &ec_config.param_out,
212 },
213 {
214 .name = "passin",
215 .argname = "source",
216 .desc = "Input file passphrase source",
217 .type = OPTION_ARG,
218 .opt.arg = &ec_config.passargin,
219 },
220 {
221 .name = "passout",
222 .argname = "source",
223 .desc = "Output file passphrase source",
224 .type = OPTION_ARG,
225 .opt.arg = &ec_config.passargout,
226 },
227 {
228 .name = "pubin",
229 .desc = "Read public key instead of private key from input",
230 .type = OPTION_FLAG,
231 .opt.flag = &ec_config.pubin,
232 },
233 {
234 .name = "pubout",
235 .desc = "Output public key instead of private key in output",
236 .type = OPTION_FLAG,
237 .opt.flag = &ec_config.pubout,
238 },
239 {
240 .name = "text",
241 .desc = "Print the public/private key components and parameters",
242 .type = OPTION_FLAG,
243 .opt.flag = &ec_config.text,
244 },
245 {
246 .name = NULL,
247 .desc = "Cipher to encrypt the output if using PEM format",
248 .type = OPTION_ARGV_FUNC,
249 .opt.argvfunc = ec_opt_enc,
250 },
251 { NULL },
252};
253
254static void
255show_ciphers(const OBJ_NAME *name, void *arg)
256{
257 static int n;
258
259 if (!islower((unsigned char)*name->name))
260 return;
261
262 fprintf(stderr, " -%-24s%s", name->name, (++n % 3 ? "" : "\n"));
263}
264
265static void
266ec_usage(void)
267{
268 fprintf(stderr,
269 "usage: ec [-conv_form form] [-engine id] [-in file]\n"
270 " [-inform format] [-noout] [-out file] [-outform format]\n"
271 " [-param_enc type] [-param_out] [-passin file]\n"
272 " [-passout file] [-pubin] [-pubout] [-text] [-ciphername]\n\n");
273 options_usage(ec_options);
274
275 fprintf(stderr, "\n");
276
277 fprintf(stderr, "Valid ciphername values:\n\n");
278 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_ciphers, NULL);
279 fprintf(stderr, "\n");
280}
84 281
85int ec_main(int, char **); 282int ec_main(int, char **);
86 283
@@ -90,174 +287,54 @@ ec_main(int argc, char **argv)
90 int ret = 1; 287 int ret = 1;
91 EC_KEY *eckey = NULL; 288 EC_KEY *eckey = NULL;
92 const EC_GROUP *group; 289 const EC_GROUP *group;
93 int i, badops = 0; 290 int i;
94 const EVP_CIPHER *enc = NULL;
95 BIO *in = NULL, *out = NULL; 291 BIO *in = NULL, *out = NULL;
96 int informat, outformat, text = 0, noout = 0;
97 int pubin = 0, pubout = 0, param_out = 0;
98 char *infile, *outfile, *prog, *engine;
99 char *passargin = NULL, *passargout = NULL;
100 char *passin = NULL, *passout = NULL; 292 char *passin = NULL, *passout = NULL;
101 point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
102 int new_form = 0;
103 int asn1_flag = OPENSSL_EC_NAMED_CURVE;
104 int new_asn1_flag = 0;
105
106 engine = NULL;
107 infile = NULL;
108 outfile = NULL;
109 informat = FORMAT_PEM;
110 outformat = FORMAT_PEM;
111
112 prog = argv[0];
113 argc--;
114 argv++;
115 while (argc >= 1) {
116 if (strcmp(*argv, "-inform") == 0) {
117 if (--argc < 1)
118 goto bad;
119 informat = str2fmt(*(++argv));
120 } else if (strcmp(*argv, "-outform") == 0) {
121 if (--argc < 1)
122 goto bad;
123 outformat = str2fmt(*(++argv));
124 } else if (strcmp(*argv, "-in") == 0) {
125 if (--argc < 1)
126 goto bad;
127 infile = *(++argv);
128 } else if (strcmp(*argv, "-out") == 0) {
129 if (--argc < 1)
130 goto bad;
131 outfile = *(++argv);
132 } else if (strcmp(*argv, "-passin") == 0) {
133 if (--argc < 1)
134 goto bad;
135 passargin = *(++argv);
136 } else if (strcmp(*argv, "-passout") == 0) {
137 if (--argc < 1)
138 goto bad;
139 passargout = *(++argv);
140 } else if (strcmp(*argv, "-engine") == 0) {
141 if (--argc < 1)
142 goto bad;
143 engine = *(++argv);
144 } else if (strcmp(*argv, "-noout") == 0)
145 noout = 1;
146 else if (strcmp(*argv, "-text") == 0)
147 text = 1;
148 else if (strcmp(*argv, "-conv_form") == 0) {
149 if (--argc < 1)
150 goto bad;
151 ++argv;
152 new_form = 1;
153 if (strcmp(*argv, "compressed") == 0)
154 form = POINT_CONVERSION_COMPRESSED;
155 else if (strcmp(*argv, "uncompressed") == 0)
156 form = POINT_CONVERSION_UNCOMPRESSED;
157 else if (strcmp(*argv, "hybrid") == 0)
158 form = POINT_CONVERSION_HYBRID;
159 else
160 goto bad;
161 } else if (strcmp(*argv, "-param_enc") == 0) {
162 if (--argc < 1)
163 goto bad;
164 ++argv;
165 new_asn1_flag = 1;
166 if (strcmp(*argv, "named_curve") == 0)
167 asn1_flag = OPENSSL_EC_NAMED_CURVE;
168 else if (strcmp(*argv, "explicit") == 0)
169 asn1_flag = 0;
170 else
171 goto bad;
172 } else if (strcmp(*argv, "-param_out") == 0)
173 param_out = 1;
174 else if (strcmp(*argv, "-pubin") == 0)
175 pubin = 1;
176 else if (strcmp(*argv, "-pubout") == 0)
177 pubout = 1;
178 else if ((enc = EVP_get_cipherbyname(&(argv[0][1]))) == NULL) {
179 BIO_printf(bio_err, "unknown option %s\n", *argv);
180 badops = 1;
181 break;
182 }
183 argc--;
184 argv++;
185 }
186 293
187 if (badops) { 294 memset(&ec_config, 0, sizeof(ec_config));
188bad: 295
189 BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); 296 ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
190 BIO_printf(bio_err, "where options are\n"); 297 ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
191 BIO_printf(bio_err, " -inform arg input format - " 298 ec_config.informat = FORMAT_PEM;
192 "DER or PEM\n"); 299 ec_config.outformat = FORMAT_PEM;
193 BIO_printf(bio_err, " -outform arg output format - " 300
194 "DER or PEM\n"); 301 if (options_parse(argc, argv, ec_options, NULL, NULL) != 0) {
195 BIO_printf(bio_err, " -in arg input file\n"); 302 ec_usage();
196 BIO_printf(bio_err, " -passin arg input file pass "
197 "phrase source\n");
198 BIO_printf(bio_err, " -out arg output file\n");
199 BIO_printf(bio_err, " -passout arg output file pass "
200 "phrase source\n");
201 BIO_printf(bio_err, " -engine e use engine e, "
202 "possibly a hardware device.\n");
203 BIO_printf(bio_err, " -des encrypt PEM output, "
204 "instead of 'des' every other \n"
205 " cipher "
206 "supported by OpenSSL can be used\n");
207 BIO_printf(bio_err, " -text print the key\n");
208 BIO_printf(bio_err, " -noout don't print key out\n");
209 BIO_printf(bio_err, " -param_out print the elliptic "
210 "curve parameters\n");
211 BIO_printf(bio_err, " -conv_form arg specifies the "
212 "point conversion form \n");
213 BIO_printf(bio_err, " possible values:"
214 " compressed\n");
215 BIO_printf(bio_err, " "
216 " uncompressed (default)\n");
217 BIO_printf(bio_err, " "
218 " hybrid\n");
219 BIO_printf(bio_err, " -param_enc arg specifies the way"
220 " the ec parameters are encoded\n");
221 BIO_printf(bio_err, " in the asn1 der "
222 "encoding\n");
223 BIO_printf(bio_err, " possible values:"
224 " named_curve (default)\n");
225 BIO_printf(bio_err, " "
226 "explicit\n");
227 goto end; 303 goto end;
228 } 304 }
229 305
230#ifndef OPENSSL_NO_ENGINE 306#ifndef OPENSSL_NO_ENGINE
231 setup_engine(bio_err, engine, 0); 307 setup_engine(bio_err, ec_config.engine, 0);
232#endif 308#endif
233 309
234 if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 310 if (!app_passwd(bio_err, ec_config.passargin, ec_config.passargout,
311 &passin, &passout)) {
235 BIO_printf(bio_err, "Error getting passwords\n"); 312 BIO_printf(bio_err, "Error getting passwords\n");
236 goto end; 313 goto end;
237 } 314 }
238 in = BIO_new(BIO_s_file()); 315 in = BIO_new(BIO_s_file());
239 out = BIO_new(BIO_s_file()); 316 out = BIO_new(BIO_s_file());
240 if ((in == NULL) || (out == NULL)) { 317 if (in == NULL || out == NULL) {
241 ERR_print_errors(bio_err); 318 ERR_print_errors(bio_err);
242 goto end; 319 goto end;
243 } 320 }
244 if (infile == NULL) 321 if (ec_config.infile == NULL)
245 BIO_set_fp(in, stdin, BIO_NOCLOSE); 322 BIO_set_fp(in, stdin, BIO_NOCLOSE);
246 else { 323 else {
247 if (BIO_read_filename(in, infile) <= 0) { 324 if (BIO_read_filename(in, ec_config.infile) <= 0) {
248 perror(infile); 325 perror(ec_config.infile);
249 goto end; 326 goto end;
250 } 327 }
251 } 328 }
252 329
253 BIO_printf(bio_err, "read EC key\n"); 330 BIO_printf(bio_err, "read EC key\n");
254 if (informat == FORMAT_ASN1) { 331 if (ec_config.informat == FORMAT_ASN1) {
255 if (pubin) 332 if (ec_config.pubin)
256 eckey = d2i_EC_PUBKEY_bio(in, NULL); 333 eckey = d2i_EC_PUBKEY_bio(in, NULL);
257 else 334 else
258 eckey = d2i_ECPrivateKey_bio(in, NULL); 335 eckey = d2i_ECPrivateKey_bio(in, NULL);
259 } else if (informat == FORMAT_PEM) { 336 } else if (ec_config.informat == FORMAT_PEM) {
260 if (pubin) 337 if (ec_config.pubin)
261 eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, 338 eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL,
262 NULL); 339 NULL);
263 else 340 else
@@ -272,49 +349,49 @@ bad:
272 ERR_print_errors(bio_err); 349 ERR_print_errors(bio_err);
273 goto end; 350 goto end;
274 } 351 }
275 if (outfile == NULL) { 352 if (ec_config.outfile == NULL) {
276 BIO_set_fp(out, stdout, BIO_NOCLOSE); 353 BIO_set_fp(out, stdout, BIO_NOCLOSE);
277 } else { 354 } else {
278 if (BIO_write_filename(out, outfile) <= 0) { 355 if (BIO_write_filename(out, ec_config.outfile) <= 0) {
279 perror(outfile); 356 perror(ec_config.outfile);
280 goto end; 357 goto end;
281 } 358 }
282 } 359 }
283 360
284 group = EC_KEY_get0_group(eckey); 361 group = EC_KEY_get0_group(eckey);
285 362
286 if (new_form) 363 if (ec_config.new_form)
287 EC_KEY_set_conv_form(eckey, form); 364 EC_KEY_set_conv_form(eckey, ec_config.form);
288 365
289 if (new_asn1_flag) 366 if (ec_config.new_asn1_flag)
290 EC_KEY_set_asn1_flag(eckey, asn1_flag); 367 EC_KEY_set_asn1_flag(eckey, ec_config.asn1_flag);
291 368
292 if (text) 369 if (ec_config.text)
293 if (!EC_KEY_print(out, eckey, 0)) { 370 if (!EC_KEY_print(out, eckey, 0)) {
294 perror(outfile); 371 perror(ec_config.outfile);
295 ERR_print_errors(bio_err); 372 ERR_print_errors(bio_err);
296 goto end; 373 goto end;
297 } 374 }
298 if (noout) { 375 if (ec_config.noout) {
299 ret = 0; 376 ret = 0;
300 goto end; 377 goto end;
301 } 378 }
302 BIO_printf(bio_err, "writing EC key\n"); 379 BIO_printf(bio_err, "writing EC key\n");
303 if (outformat == FORMAT_ASN1) { 380 if (ec_config.outformat == FORMAT_ASN1) {
304 if (param_out) 381 if (ec_config.param_out)
305 i = i2d_ECPKParameters_bio(out, group); 382 i = i2d_ECPKParameters_bio(out, group);
306 else if (pubin || pubout) 383 else if (ec_config.pubin || ec_config.pubout)
307 i = i2d_EC_PUBKEY_bio(out, eckey); 384 i = i2d_EC_PUBKEY_bio(out, eckey);
308 else 385 else
309 i = i2d_ECPrivateKey_bio(out, eckey); 386 i = i2d_ECPrivateKey_bio(out, eckey);
310 } else if (outformat == FORMAT_PEM) { 387 } else if (ec_config.outformat == FORMAT_PEM) {
311 if (param_out) 388 if (ec_config.param_out)
312 i = PEM_write_bio_ECPKParameters(out, group); 389 i = PEM_write_bio_ECPKParameters(out, group);
313 else if (pubin || pubout) 390 else if (ec_config.pubin || ec_config.pubout)
314 i = PEM_write_bio_EC_PUBKEY(out, eckey); 391 i = PEM_write_bio_EC_PUBKEY(out, eckey);
315 else 392 else
316 i = PEM_write_bio_ECPrivateKey(out, eckey, enc, 393 i = PEM_write_bio_ECPrivateKey(out, eckey,
317 NULL, 0, NULL, passout); 394 ec_config.enc, NULL, 0, NULL, passout);
318 } else { 395 } else {
319 BIO_printf(bio_err, "bad output format specified for " 396 BIO_printf(bio_err, "bad output format specified for "
320 "outfile\n"); 397 "outfile\n");