1 /* $OpenBSD: ec.c,v 1.2 2014/08/28 14:23:52 jsing 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 <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 74 /* -inform arg - input format - default PEM (one of DER, NET or PEM) 75 * -outform arg - output format - default PEM 76 * -in arg - input file - default stdin 77 * -out arg - output file - default stdout 78 * -des - encrypt output if PEM format with DES in cbc mode 79 * -text - print a text version 80 * -param_out - print the elliptic curve parameters 81 * -conv_form arg - specifies the point encoding form 82 * -param_enc arg - specifies the parameter encoding 83 */ 84 85 int ec_main(int, char **); 86 87 int 88 ec_main(int argc, char **argv) 89 { 90 int ret = 1; 91 EC_KEY *eckey = NULL; 92 const EC_GROUP *group; 93 int i, badops = 0; 94 const EVP_CIPHER *enc = NULL; 95 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; 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 187 if (badops) { 188 bad: 189 BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog); 190 BIO_printf(bio_err, "where options are\n"); 191 BIO_printf(bio_err, " -inform arg input format - " 192 "DER or PEM\n"); 193 BIO_printf(bio_err, " -outform arg output format - " 194 "DER or PEM\n"); 195 BIO_printf(bio_err, " -in arg input file\n"); 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; 228 } 229 230 #ifndef OPENSSL_NO_ENGINE 231 setup_engine(bio_err, engine, 0); 232 #endif 233 234 if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 235 BIO_printf(bio_err, "Error getting passwords\n"); 236 goto end; 237 } 238 in = BIO_new(BIO_s_file()); 239 out = BIO_new(BIO_s_file()); 240 if ((in == NULL) || (out == NULL)) { 241 ERR_print_errors(bio_err); 242 goto end; 243 } 244 if (infile == NULL) 245 BIO_set_fp(in, stdin, BIO_NOCLOSE); 246 else { 247 if (BIO_read_filename(in, infile) <= 0) { 248 perror(infile); 249 goto end; 250 } 251 } 252 253 BIO_printf(bio_err, "read EC key\n"); 254 if (informat == FORMAT_ASN1) { 255 if (pubin) 256 eckey = d2i_EC_PUBKEY_bio(in, NULL); 257 else 258 eckey = d2i_ECPrivateKey_bio(in, NULL); 259 } else if (informat == FORMAT_PEM) { 260 if (pubin) 261 eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, 262 NULL); 263 else 264 eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, 265 passin); 266 } else { 267 BIO_printf(bio_err, "bad input format specified for key\n"); 268 goto end; 269 } 270 if (eckey == NULL) { 271 BIO_printf(bio_err, "unable to load Key\n"); 272 ERR_print_errors(bio_err); 273 goto end; 274 } 275 if (outfile == NULL) { 276 BIO_set_fp(out, stdout, BIO_NOCLOSE); 277 } else { 278 if (BIO_write_filename(out, outfile) <= 0) { 279 perror(outfile); 280 goto end; 281 } 282 } 283 284 group = EC_KEY_get0_group(eckey); 285 286 if (new_form) 287 EC_KEY_set_conv_form(eckey, form); 288 289 if (new_asn1_flag) 290 EC_KEY_set_asn1_flag(eckey, asn1_flag); 291 292 if (text) 293 if (!EC_KEY_print(out, eckey, 0)) { 294 perror(outfile); 295 ERR_print_errors(bio_err); 296 goto end; 297 } 298 if (noout) { 299 ret = 0; 300 goto end; 301 } 302 BIO_printf(bio_err, "writing EC key\n"); 303 if (outformat == FORMAT_ASN1) { 304 if (param_out) 305 i = i2d_ECPKParameters_bio(out, group); 306 else if (pubin || pubout) 307 i = i2d_EC_PUBKEY_bio(out, eckey); 308 else 309 i = i2d_ECPrivateKey_bio(out, eckey); 310 } else if (outformat == FORMAT_PEM) { 311 if (param_out) 312 i = PEM_write_bio_ECPKParameters(out, group); 313 else if (pubin || pubout) 314 i = PEM_write_bio_EC_PUBKEY(out, eckey); 315 else 316 i = PEM_write_bio_ECPrivateKey(out, eckey, enc, 317 NULL, 0, NULL, passout); 318 } else { 319 BIO_printf(bio_err, "bad output format specified for " 320 "outfile\n"); 321 goto end; 322 } 323 324 if (!i) { 325 BIO_printf(bio_err, "unable to write private key\n"); 326 ERR_print_errors(bio_err); 327 } else 328 ret = 0; 329 end: 330 BIO_free(in); 331 if (out) 332 BIO_free_all(out); 333 if (eckey) 334 EC_KEY_free(eckey); 335 free(passin); 336 free(passout); 337 338 return (ret); 339 } 340 #endif 341