Annotation of src/usr.bin/openssl/ec.c, Revision 1.12
1.12 ! inoguchi 1: /* $OpenBSD: ec.c,v 1.11 2018/02/07 05:47:55 jsing Exp $ */
1.1 jsing 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 <stdio.h>
64: #include <stdlib.h>
65: #include <string.h>
66:
67: #include "apps.h"
68:
69: #include <openssl/bio.h>
70: #include <openssl/err.h>
71: #include <openssl/evp.h>
72: #include <openssl/pem.h>
73:
1.3 doug 74: static struct {
75: int asn1_flag;
76: const EVP_CIPHER *enc;
77: point_conversion_form_t form;
78: char *infile;
79: int informat;
80: char *outfile;
81: int outformat;
82: int new_asn1_flag;
83: int new_form;
84: int noout;
85: int param_out;
86: char *passargin;
87: char *passargout;
88: int pubin;
89: int pubout;
90: int text;
91: } ec_config;
92:
93: static int
94: ec_opt_enc(int argc, char **argv, int *argsused)
95: {
96: char *name = argv[0];
97:
98: if (*name++ != '-')
99: return (1);
100:
101: if ((ec_config.enc = EVP_get_cipherbyname(name)) != NULL) {
102: *argsused = 1;
103: return (0);
104: }
105:
106: return (1);
107: }
108:
109: static int
110: ec_opt_form(char *arg)
111: {
112: if (strcmp(arg, "compressed") == 0)
113: ec_config.form = POINT_CONVERSION_COMPRESSED;
114: else if (strcmp(arg, "uncompressed") == 0)
115: ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
116: else if (strcmp(arg, "hybrid") == 0)
117: ec_config.form = POINT_CONVERSION_HYBRID;
118: else {
119: fprintf(stderr, "Invalid point conversion: %s\n", arg);
120: return (1);
121: }
122:
123: ec_config.new_form = 1;
124: return (0);
125: }
126:
127: static int
128: ec_opt_named(char *arg)
129: {
130: if (strcmp(arg, "named_curve") == 0)
131: ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
132: else if (strcmp(arg, "explicit") == 0)
133: ec_config.asn1_flag = 0;
134: else {
135: fprintf(stderr, "Invalid curve type: %s\n", arg);
136: return (1);
137: }
138:
139: ec_config.new_asn1_flag = 1;
140: return (0);
141: }
142:
143: static struct option ec_options[] = {
144: {
145: .name = "conv_form",
146: .argname = "form",
147: .desc = "Specify the point conversion form (default"
148: " \"named_curve\")",
149: .type = OPTION_ARG_FUNC,
150: .opt.argfunc = ec_opt_form,
151: },
152: {
153: .name = "in",
154: .argname = "file",
155: .desc = "Input file (default stdin)",
156: .type = OPTION_ARG,
157: .opt.arg = &ec_config.infile,
158: },
159: {
160: .name = "inform",
161: .argname = "format",
162: .desc = "Input format (DER or PEM (default))",
163: .type = OPTION_ARG_FORMAT,
164: .opt.value = &ec_config.informat,
165: },
166: {
167: .name = "noout",
168: .desc = "No output",
169: .type = OPTION_FLAG,
170: .opt.flag = &ec_config.noout,
171: },
172: {
173: .name = "out",
174: .argname = "file",
175: .desc = "Output file (default stdout)",
176: .type = OPTION_ARG,
177: .opt.arg = &ec_config.outfile,
178: },
179: {
180: .name = "outform",
181: .argname = "format",
182: .desc = "Output format (DER or PEM (default))",
183: .type = OPTION_ARG_FORMAT,
184: .opt.value = &ec_config.outformat,
185: },
186: {
187: .name = "param_enc",
188: .argname = "type",
189: .desc = "Specify the way the ec parameters are encoded"
190: " (default \"uncompressed\")",
191: .type = OPTION_ARG_FUNC,
192: .opt.argfunc = ec_opt_named,
193: },
194: {
195: .name = "param_out",
196: .desc = "Print the elliptic curve parameters",
197: .type = OPTION_FLAG,
198: .opt.flag = &ec_config.param_out,
199: },
200: {
201: .name = "passin",
202: .argname = "source",
203: .desc = "Input file passphrase source",
204: .type = OPTION_ARG,
205: .opt.arg = &ec_config.passargin,
206: },
207: {
208: .name = "passout",
209: .argname = "source",
210: .desc = "Output file passphrase source",
211: .type = OPTION_ARG,
212: .opt.arg = &ec_config.passargout,
213: },
214: {
215: .name = "pubin",
216: .desc = "Read public key instead of private key from input",
217: .type = OPTION_FLAG,
218: .opt.flag = &ec_config.pubin,
219: },
220: {
221: .name = "pubout",
222: .desc = "Output public key instead of private key in output",
223: .type = OPTION_FLAG,
224: .opt.flag = &ec_config.pubout,
225: },
226: {
227: .name = "text",
228: .desc = "Print the public/private key components and parameters",
229: .type = OPTION_FLAG,
230: .opt.flag = &ec_config.text,
231: },
232: {
233: .name = NULL,
234: .desc = "Cipher to encrypt the output if using PEM format",
235: .type = OPTION_ARGV_FUNC,
236: .opt.argvfunc = ec_opt_enc,
237: },
238: { NULL },
239: };
240:
241: static void
242: ec_usage(void)
243: {
244: fprintf(stderr,
1.5 bcook 245: "usage: ec [-conv_form form] [-in file]\n"
1.3 doug 246: " [-inform format] [-noout] [-out file] [-outform format]\n"
247: " [-param_enc type] [-param_out] [-passin file]\n"
248: " [-passout file] [-pubin] [-pubout] [-text] [-ciphername]\n\n");
249: options_usage(ec_options);
250:
251: fprintf(stderr, "\n");
252:
253: fprintf(stderr, "Valid ciphername values:\n\n");
1.12 ! inoguchi 254: OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, NULL);
1.3 doug 255: fprintf(stderr, "\n");
256: }
1.1 jsing 257:
258: int
259: ec_main(int argc, char **argv)
260: {
261: int ret = 1;
262: EC_KEY *eckey = NULL;
263: const EC_GROUP *group;
1.3 doug 264: int i;
1.1 jsing 265: BIO *in = NULL, *out = NULL;
266: char *passin = NULL, *passout = NULL;
1.6 doug 267:
268: if (single_execution) {
1.9 deraadt 269: if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.6 doug 270: perror("pledge");
1.8 doug 271: exit(1);
272: }
1.6 doug 273: }
1.1 jsing 274:
1.3 doug 275: memset(&ec_config, 0, sizeof(ec_config));
276:
277: ec_config.asn1_flag = OPENSSL_EC_NAMED_CURVE;
278: ec_config.form = POINT_CONVERSION_UNCOMPRESSED;
279: ec_config.informat = FORMAT_PEM;
280: ec_config.outformat = FORMAT_PEM;
281:
282: if (options_parse(argc, argv, ec_options, NULL, NULL) != 0) {
283: ec_usage();
1.1 jsing 284: goto end;
285: }
286:
1.3 doug 287: if (!app_passwd(bio_err, ec_config.passargin, ec_config.passargout,
288: &passin, &passout)) {
1.1 jsing 289: BIO_printf(bio_err, "Error getting passwords\n");
290: goto end;
291: }
292: in = BIO_new(BIO_s_file());
293: out = BIO_new(BIO_s_file());
1.3 doug 294: if (in == NULL || out == NULL) {
1.1 jsing 295: ERR_print_errors(bio_err);
296: goto end;
297: }
1.3 doug 298: if (ec_config.infile == NULL)
1.1 jsing 299: BIO_set_fp(in, stdin, BIO_NOCLOSE);
300: else {
1.3 doug 301: if (BIO_read_filename(in, ec_config.infile) <= 0) {
302: perror(ec_config.infile);
1.1 jsing 303: goto end;
304: }
305: }
306:
307: BIO_printf(bio_err, "read EC key\n");
1.3 doug 308: if (ec_config.informat == FORMAT_ASN1) {
309: if (ec_config.pubin)
1.1 jsing 310: eckey = d2i_EC_PUBKEY_bio(in, NULL);
311: else
312: eckey = d2i_ECPrivateKey_bio(in, NULL);
1.3 doug 313: } else if (ec_config.informat == FORMAT_PEM) {
314: if (ec_config.pubin)
1.1 jsing 315: eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL,
316: NULL);
317: else
318: eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL,
319: passin);
320: } else {
321: BIO_printf(bio_err, "bad input format specified for key\n");
322: goto end;
323: }
324: if (eckey == NULL) {
325: BIO_printf(bio_err, "unable to load Key\n");
326: ERR_print_errors(bio_err);
327: goto end;
328: }
1.3 doug 329: if (ec_config.outfile == NULL) {
1.1 jsing 330: BIO_set_fp(out, stdout, BIO_NOCLOSE);
331: } else {
1.3 doug 332: if (BIO_write_filename(out, ec_config.outfile) <= 0) {
333: perror(ec_config.outfile);
1.1 jsing 334: goto end;
335: }
336: }
337:
338: group = EC_KEY_get0_group(eckey);
339:
1.3 doug 340: if (ec_config.new_form)
341: EC_KEY_set_conv_form(eckey, ec_config.form);
1.1 jsing 342:
1.3 doug 343: if (ec_config.new_asn1_flag)
344: EC_KEY_set_asn1_flag(eckey, ec_config.asn1_flag);
1.1 jsing 345:
1.3 doug 346: if (ec_config.text)
1.1 jsing 347: if (!EC_KEY_print(out, eckey, 0)) {
1.3 doug 348: perror(ec_config.outfile);
1.1 jsing 349: ERR_print_errors(bio_err);
350: goto end;
351: }
1.3 doug 352: if (ec_config.noout) {
1.1 jsing 353: ret = 0;
354: goto end;
355: }
356: BIO_printf(bio_err, "writing EC key\n");
1.3 doug 357: if (ec_config.outformat == FORMAT_ASN1) {
358: if (ec_config.param_out)
1.1 jsing 359: i = i2d_ECPKParameters_bio(out, group);
1.3 doug 360: else if (ec_config.pubin || ec_config.pubout)
1.1 jsing 361: i = i2d_EC_PUBKEY_bio(out, eckey);
362: else
363: i = i2d_ECPrivateKey_bio(out, eckey);
1.3 doug 364: } else if (ec_config.outformat == FORMAT_PEM) {
365: if (ec_config.param_out)
1.1 jsing 366: i = PEM_write_bio_ECPKParameters(out, group);
1.3 doug 367: else if (ec_config.pubin || ec_config.pubout)
1.1 jsing 368: i = PEM_write_bio_EC_PUBKEY(out, eckey);
369: else
1.3 doug 370: i = PEM_write_bio_ECPrivateKey(out, eckey,
371: ec_config.enc, NULL, 0, NULL, passout);
1.1 jsing 372: } else {
373: BIO_printf(bio_err, "bad output format specified for "
374: "outfile\n");
375: goto end;
376: }
377:
378: if (!i) {
379: BIO_printf(bio_err, "unable to write private key\n");
380: ERR_print_errors(bio_err);
381: } else
382: ret = 0;
1.11 jsing 383: end:
1.1 jsing 384: BIO_free(in);
1.10 jsing 385: BIO_free_all(out);
386: EC_KEY_free(eckey);
1.1 jsing 387: free(passin);
388: free(passout);
389:
390: return (ret);
391: }
392: #endif