GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/openssl/ec.c Lines: 64 120 53.3 %
Date: 2017-11-13 Branches: 32 72 44.4 %

Line Branch Exec Source
1
/* $OpenBSD: ec.c,v 1.9 2017/01/20 08:57:12 deraadt Exp $ */
2
/*
3
 * Written by Nils Larsch for the OpenSSL project.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    openssl-core@openssl.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
#include <openssl/opensslconf.h>
60
61
#ifndef OPENSSL_NO_EC
62
63
#include <ctype.h>
64
#include <stdio.h>
65
#include <stdlib.h>
66
#include <string.h>
67
68
#include "apps.h"
69
70
#include <openssl/bio.h>
71
#include <openssl/err.h>
72
#include <openssl/evp.h>
73
#include <openssl/pem.h>
74
75
static struct {
76
	int asn1_flag;
77
	const EVP_CIPHER *enc;
78
	point_conversion_form_t form;
79
	char *infile;
80
	int informat;
81
	char *outfile;
82
	int outformat;
83
	int new_asn1_flag;
84
	int new_form;
85
	int noout;
86
	int param_out;
87
	char *passargin;
88
	char *passargout;
89
	int pubin;
90
	int pubout;
91
	int text;
92
} ec_config;
93
94
static int
95
ec_opt_enc(int argc, char **argv, int *argsused)
96
{
97
8
	char *name = argv[0];
98
99
4
	if (*name++ != '-')
100
		return (1);
101
102
4
	if ((ec_config.enc = EVP_get_cipherbyname(name)) != NULL) {
103
		*argsused = 1;
104
		return (0);
105
	}
106
107
4
	return (1);
108
4
}
109
110
static int
111
ec_opt_form(char *arg)
112
{
113
	if (strcmp(arg, "compressed") == 0)
114
		ec_config.form = POINT_CONVERSION_COMPRESSED;
115
	else if (strcmp(arg, "uncompressed") == 0)
116
		ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
117
	else if (strcmp(arg, "hybrid") == 0)
118
		ec_config.form = POINT_CONVERSION_HYBRID;
119
	else {
120
		fprintf(stderr, "Invalid point conversion: %s\n", arg);
121
		return (1);
122
	}
123
124
	ec_config.new_form = 1;
125
	return (0);
126
}
127
128
static int
129
ec_opt_named(char *arg)
130
{
131
	if (strcmp(arg, "named_curve") == 0)
132
		ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
133
	else if (strcmp(arg, "explicit") == 0)
134
		ec_config.asn1_flag = 0;
135
	else {
136
		fprintf(stderr, "Invalid curve type: %s\n", arg);
137
		return (1);
138
	}
139
140
	ec_config.new_asn1_flag = 1;
141
	return (0);
142
}
143
144
static struct option ec_options[] = {
145
	{
146
		.name = "conv_form",
147
		.argname = "form",
148
		.desc = "Specify the point conversion form (default"
149
		    " \"named_curve\")",
150
		.type = OPTION_ARG_FUNC,
151
		.opt.argfunc = ec_opt_form,
152
	},
153
	{
154
		.name = "in",
155
		.argname = "file",
156
		.desc = "Input file (default stdin)",
157
		.type = OPTION_ARG,
158
		.opt.arg = &ec_config.infile,
159
	},
160
	{
161
		.name = "inform",
162
		.argname = "format",
163
		.desc = "Input format (DER or PEM (default))",
164
		.type = OPTION_ARG_FORMAT,
165
		.opt.value = &ec_config.informat,
166
	},
167
	{
168
		.name = "noout",
169
		.desc = "No output",
170
		.type = OPTION_FLAG,
171
		.opt.flag = &ec_config.noout,
172
	},
173
	{
174
		.name = "out",
175
		.argname = "file",
176
		.desc = "Output file (default stdout)",
177
		.type = OPTION_ARG,
178
		.opt.arg = &ec_config.outfile,
179
	},
180
	{
181
		.name = "outform",
182
		.argname = "format",
183
		.desc = "Output format (DER or PEM (default))",
184
		.type = OPTION_ARG_FORMAT,
185
		.opt.value = &ec_config.outformat,
186
	},
187
	{
188
		.name = "param_enc",
189
		.argname = "type",
190
		.desc = "Specify the way the ec parameters are encoded"
191
		    " (default \"uncompressed\")",
192
		.type = OPTION_ARG_FUNC,
193
		.opt.argfunc = ec_opt_named,
194
	},
195
	{
196
		.name = "param_out",
197
		.desc = "Print the elliptic curve parameters",
198
		.type = OPTION_FLAG,
199
		.opt.flag = &ec_config.param_out,
200
	},
201
	{
202
		.name = "passin",
203
		.argname = "source",
204
		.desc = "Input file passphrase source",
205
		.type = OPTION_ARG,
206
		.opt.arg = &ec_config.passargin,
207
	},
208
	{
209
		.name = "passout",
210
		.argname = "source",
211
		.desc = "Output file passphrase source",
212
		.type = OPTION_ARG,
213
		.opt.arg = &ec_config.passargout,
214
	},
215
	{
216
		.name = "pubin",
217
		.desc = "Read public key instead of private key from input",
218
		.type = OPTION_FLAG,
219
		.opt.flag = &ec_config.pubin,
220
	},
221
	{
222
		.name = "pubout",
223
		.desc = "Output public key instead of private key in output",
224
		.type = OPTION_FLAG,
225
		.opt.flag = &ec_config.pubout,
226
	},
227
	{
228
		.name = "text",
229
		.desc = "Print the public/private key components and parameters",
230
		.type = OPTION_FLAG,
231
		.opt.flag = &ec_config.text,
232
	},
233
	{
234
		.name = NULL,
235
		.desc = "Cipher to encrypt the output if using PEM format",
236
		.type = OPTION_ARGV_FUNC,
237
		.opt.argvfunc = ec_opt_enc,
238
	},
239
	{ NULL },
240
};
241
242
static void
243
show_ciphers(const OBJ_NAME *name, void *arg)
244
{
245
	static int n;
246
247
1624
	if (!islower((unsigned char)*name->name))
248
		return;
249
250
424
	fprintf(stderr, " -%-24s%s", name->name, (++n % 3 ? "" : "\n"));
251
1236
}
252
253
static void
254
ec_usage(void)
255
{
256
8
	fprintf(stderr,
257
	    "usage: ec [-conv_form form] [-in file]\n"
258
	    "    [-inform format] [-noout] [-out file] [-outform format]\n"
259
	    "    [-param_enc type] [-param_out] [-passin file]\n"
260
	    "    [-passout file] [-pubin] [-pubout] [-text] [-ciphername]\n\n");
261
4
	options_usage(ec_options);
262
263
4
	fprintf(stderr, "\n");
264
265
4
	fprintf(stderr, "Valid ciphername values:\n\n");
266
4
	OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_ciphers, NULL);
267
4
	fprintf(stderr, "\n");
268
4
}
269
270
int
271
ec_main(int argc, char **argv)
272
{
273
	int ret = 1;
274
	EC_KEY *eckey = NULL;
275
	const EC_GROUP *group;
276
	int i;
277
	BIO *in = NULL, *out = NULL;
278
728
	char *passin = NULL, *passout = NULL;
279
280
364
	if (single_execution) {
281
364
		if (pledge("stdio cpath wpath rpath tty flock", NULL) == -1) {
282
			perror("pledge");
283
			exit(1);
284
		}
285
	}
286
287
364
	memset(&ec_config, 0, sizeof(ec_config));
288
289
364
	ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
290
364
	ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
291
364
	ec_config.informat = FORMAT_PEM;
292
364
	ec_config.outformat = FORMAT_PEM;
293
294
364
	if (options_parse(argc, argv, ec_options, NULL, NULL) != 0) {
295
4
		ec_usage();
296
4
		goto end;
297
	}
298
299
360
	if (!app_passwd(bio_err, ec_config.passargin, ec_config.passargout,
300
	    &passin, &passout)) {
301
		BIO_printf(bio_err, "Error getting passwords\n");
302
		goto end;
303
	}
304
360
	in = BIO_new(BIO_s_file());
305
360
	out = BIO_new(BIO_s_file());
306
360
	if (in == NULL || out == NULL) {
307
		ERR_print_errors(bio_err);
308
		goto end;
309
	}
310
360
	if (ec_config.infile == NULL)
311
		BIO_set_fp(in, stdin, BIO_NOCLOSE);
312
	else {
313
360
		if (BIO_read_filename(in, ec_config.infile) <= 0) {
314
			perror(ec_config.infile);
315
			goto end;
316
		}
317
	}
318
319
360
	BIO_printf(bio_err, "read EC key\n");
320
360
	if (ec_config.informat == FORMAT_ASN1) {
321
		if (ec_config.pubin)
322
			eckey = d2i_EC_PUBKEY_bio(in, NULL);
323
		else
324
			eckey = d2i_ECPrivateKey_bio(in, NULL);
325
360
	} else if (ec_config.informat == FORMAT_PEM) {
326
360
		if (ec_config.pubin)
327
			eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL,
328
			    NULL);
329
		else
330
360
			eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL,
331
360
			    passin);
332
	} else {
333
		BIO_printf(bio_err, "bad input format specified for key\n");
334
		goto end;
335
	}
336
360
	if (eckey == NULL) {
337
		BIO_printf(bio_err, "unable to load Key\n");
338
		ERR_print_errors(bio_err);
339
		goto end;
340
	}
341
360
	if (ec_config.outfile == NULL) {
342
		BIO_set_fp(out, stdout, BIO_NOCLOSE);
343
	} else {
344
360
		if (BIO_write_filename(out, ec_config.outfile) <= 0) {
345
			perror(ec_config.outfile);
346
			goto end;
347
		}
348
	}
349
350
360
	group = EC_KEY_get0_group(eckey);
351
352
360
	if (ec_config.new_form)
353
		EC_KEY_set_conv_form(eckey, ec_config.form);
354
355
360
	if (ec_config.new_asn1_flag)
356
		EC_KEY_set_asn1_flag(eckey, ec_config.asn1_flag);
357
358
360
	if (ec_config.text)
359
360
		if (!EC_KEY_print(out, eckey, 0)) {
360
			perror(ec_config.outfile);
361
			ERR_print_errors(bio_err);
362
			goto end;
363
		}
364
360
	if (ec_config.noout) {
365
		ret = 0;
366
		goto end;
367
	}
368
360
	BIO_printf(bio_err, "writing EC key\n");
369
360
	if (ec_config.outformat == FORMAT_ASN1) {
370
		if (ec_config.param_out)
371
			i = i2d_ECPKParameters_bio(out, group);
372
		else if (ec_config.pubin || ec_config.pubout)
373
			i = i2d_EC_PUBKEY_bio(out, eckey);
374
		else
375
			i = i2d_ECPrivateKey_bio(out, eckey);
376
360
	} else if (ec_config.outformat == FORMAT_PEM) {
377
360
		if (ec_config.param_out)
378
			i = PEM_write_bio_ECPKParameters(out, group);
379
360
		else if (ec_config.pubin || ec_config.pubout)
380
			i = PEM_write_bio_EC_PUBKEY(out, eckey);
381
		else
382
360
			i = PEM_write_bio_ECPrivateKey(out, eckey,
383
360
			    ec_config.enc, NULL, 0, NULL, passout);
384
	} else {
385
		BIO_printf(bio_err, "bad output format specified for "
386
		    "outfile\n");
387
		goto end;
388
	}
389
390
360
	if (!i) {
391
		BIO_printf(bio_err, "unable to write private key\n");
392
		ERR_print_errors(bio_err);
393
	} else
394
		ret = 0;
395
end:
396
364
	BIO_free(in);
397
364
	if (out)
398
360
		BIO_free_all(out);
399
364
	if (eckey)
400
360
		EC_KEY_free(eckey);
401
364
	free(passin);
402
364
	free(passout);
403
404
364
	return (ret);
405
364
}
406
#endif