Home | History | Annotate | Download | only in apps
      1 /* Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL
      2  * project 2006.
      3  */
      4 /* ====================================================================
      5  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in
     16  *    the documentation and/or other materials provided with the
     17  *    distribution.
     18  *
     19  * 3. All advertising materials mentioning features or use of this
     20  *    software must display the following acknowledgment:
     21  *    "This product includes software developed by the OpenSSL Project
     22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     23  *
     24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     25  *    endorse or promote products derived from this software without
     26  *    prior written permission. For written permission, please contact
     27  *    licensing (at) OpenSSL.org.
     28  *
     29  * 5. Products derived from this software may not be called "OpenSSL"
     30  *    nor may "OpenSSL" appear in their names without prior written
     31  *    permission of the OpenSSL Project.
     32  *
     33  * 6. Redistributions of any form whatsoever must retain the following
     34  *    acknowledgment:
     35  *    "This product includes software developed by the OpenSSL Project
     36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     37  *
     38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     49  * OF THE POSSIBILITY OF SUCH DAMAGE.
     50  * ====================================================================
     51  *
     52  * This product includes cryptographic software written by Eric Young
     53  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     54  * Hudson (tjh (at) cryptsoft.com).
     55  *
     56  */
     57 
     58 
     59 #include "apps.h"
     60 #include <string.h>
     61 #include <openssl/err.h>
     62 #include <openssl/pem.h>
     63 #include <openssl/evp.h>
     64 
     65 #define KEY_PRIVKEY	1
     66 #define KEY_PUBKEY	2
     67 #define KEY_CERT	3
     68 
     69 static void usage(void);
     70 
     71 #undef PROG
     72 
     73 #define PROG pkeyutl_main
     74 
     75 static EVP_PKEY_CTX *init_ctx(int *pkeysize,
     76 				char *keyfile, int keyform, int key_type,
     77 				char *passargin, int pkey_op, ENGINE *e);
     78 
     79 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
     80 							const char *file);
     81 
     82 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
     83 		unsigned char *out, size_t *poutlen,
     84 		unsigned char *in, size_t inlen);
     85 
     86 int MAIN(int argc, char **);
     87 
     88 int MAIN(int argc, char **argv)
     89 {
     90 	BIO *in = NULL, *out = NULL;
     91 	char *infile = NULL, *outfile = NULL, *sigfile = NULL;
     92 	ENGINE *e = NULL;
     93 	int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
     94 	int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
     95 	char badarg = 0, rev = 0;
     96 	char hexdump = 0, asn1parse = 0;
     97 	EVP_PKEY_CTX *ctx = NULL;
     98 	char *passargin = NULL;
     99 	int keysize = -1;
    100 
    101 	unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
    102 	size_t buf_outlen;
    103 	int buf_inlen = 0, siglen = -1;
    104 
    105 	int ret = 1, rv = -1;
    106 
    107 	argc--;
    108 	argv++;
    109 
    110 	if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    111 
    112 	if (!load_config(bio_err, NULL))
    113 		goto end;
    114 	ERR_load_crypto_strings();
    115 	OpenSSL_add_all_algorithms();
    116 
    117 	while(argc >= 1)
    118 		{
    119 		if (!strcmp(*argv,"-in"))
    120 			{
    121 			if (--argc < 1) badarg = 1;
    122                         else infile= *(++argv);
    123 			}
    124 		else if (!strcmp(*argv,"-out"))
    125 			{
    126 			if (--argc < 1) badarg = 1;
    127 			else outfile= *(++argv);
    128 			}
    129 		else if (!strcmp(*argv,"-sigfile"))
    130 			{
    131 			if (--argc < 1) badarg = 1;
    132 			else sigfile= *(++argv);
    133 			}
    134 		else if(!strcmp(*argv, "-inkey"))
    135 			{
    136 			if (--argc < 1)
    137 				badarg = 1;
    138 			else
    139 				{
    140 				ctx = init_ctx(&keysize,
    141 						*(++argv), keyform, key_type,
    142 						passargin, pkey_op, e);
    143 				if (!ctx)
    144 					{
    145 					BIO_puts(bio_err,
    146 						"Error initializing context\n");
    147 					ERR_print_errors(bio_err);
    148 					badarg = 1;
    149 					}
    150 				}
    151 			}
    152 		else if (!strcmp(*argv,"-peerkey"))
    153 			{
    154 			if (--argc < 1)
    155 				badarg = 1;
    156 			else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
    157 				badarg = 1;
    158 			}
    159 		else if (!strcmp(*argv,"-passin"))
    160 			{
    161 			if (--argc < 1) badarg = 1;
    162 			else passargin= *(++argv);
    163 			}
    164 		else if (strcmp(*argv,"-peerform") == 0)
    165 			{
    166 			if (--argc < 1) badarg = 1;
    167 			else peerform=str2fmt(*(++argv));
    168 			}
    169 		else if (strcmp(*argv,"-keyform") == 0)
    170 			{
    171 			if (--argc < 1) badarg = 1;
    172 			else keyform=str2fmt(*(++argv));
    173 			}
    174 #ifndef OPENSSL_NO_ENGINE
    175 		else if(!strcmp(*argv, "-engine"))
    176 			{
    177 			if (--argc < 1)
    178 				badarg = 1;
    179 			else
    180 				e = setup_engine(bio_err, *(++argv), 0);
    181 			}
    182 #endif
    183 		else if(!strcmp(*argv, "-pubin"))
    184 			key_type = KEY_PUBKEY;
    185 		else if(!strcmp(*argv, "-certin"))
    186 			key_type = KEY_CERT;
    187 		else if(!strcmp(*argv, "-asn1parse"))
    188 			asn1parse = 1;
    189 		else if(!strcmp(*argv, "-hexdump"))
    190 			hexdump = 1;
    191 		else if(!strcmp(*argv, "-sign"))
    192 			pkey_op = EVP_PKEY_OP_SIGN;
    193 		else if(!strcmp(*argv, "-verify"))
    194 			pkey_op = EVP_PKEY_OP_VERIFY;
    195 		else if(!strcmp(*argv, "-verifyrecover"))
    196 			pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
    197 		else if(!strcmp(*argv, "-rev"))
    198 			rev = 1;
    199 		else if(!strcmp(*argv, "-encrypt"))
    200 			pkey_op = EVP_PKEY_OP_ENCRYPT;
    201 		else if(!strcmp(*argv, "-decrypt"))
    202 			pkey_op = EVP_PKEY_OP_DECRYPT;
    203 		else if(!strcmp(*argv, "-derive"))
    204 			pkey_op = EVP_PKEY_OP_DERIVE;
    205 		else if (strcmp(*argv,"-pkeyopt") == 0)
    206 			{
    207 			if (--argc < 1)
    208 				badarg = 1;
    209 			else if (!ctx)
    210 				{
    211 				BIO_puts(bio_err,
    212 					"-pkeyopt command before -inkey\n");
    213 				badarg = 1;
    214 				}
    215 			else if (pkey_ctrl_string(ctx, *(++argv)) <= 0)
    216 				{
    217 				BIO_puts(bio_err, "parameter setting error\n");
    218 				ERR_print_errors(bio_err);
    219 				goto end;
    220 				}
    221 			}
    222 		else badarg = 1;
    223 		if(badarg)
    224 			{
    225 			usage();
    226 			goto end;
    227 			}
    228 		argc--;
    229 		argv++;
    230 		}
    231 
    232 	if (!ctx)
    233 		{
    234 		usage();
    235 		goto end;
    236 		}
    237 
    238 	if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY))
    239 		{
    240 		BIO_puts(bio_err, "Signature file specified for non verify\n");
    241 		goto end;
    242 		}
    243 
    244 	if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY))
    245 		{
    246 		BIO_puts(bio_err, "No signature file specified for verify\n");
    247 		goto end;
    248 		}
    249 
    250 /* FIXME: seed PRNG only if needed */
    251 	app_RAND_load_file(NULL, bio_err, 0);
    252 
    253 	if (pkey_op != EVP_PKEY_OP_DERIVE)
    254 		{
    255 		if(infile)
    256 			{
    257 			if(!(in = BIO_new_file(infile, "rb")))
    258 				{
    259 				BIO_puts(bio_err,
    260 					"Error Opening Input File\n");
    261 				ERR_print_errors(bio_err);
    262 				goto end;
    263 				}
    264 			}
    265 		else
    266 			in = BIO_new_fp(stdin, BIO_NOCLOSE);
    267 		}
    268 
    269 	if(outfile)
    270 		{
    271 		if(!(out = BIO_new_file(outfile, "wb")))
    272 			{
    273 			BIO_printf(bio_err, "Error Creating Output File\n");
    274 			ERR_print_errors(bio_err);
    275 			goto end;
    276 			}
    277 		}
    278 	else
    279 		{
    280 		out = BIO_new_fp(stdout, BIO_NOCLOSE);
    281 #ifdef OPENSSL_SYS_VMS
    282 		{
    283 		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
    284 		    out = BIO_push(tmpbio, out);
    285 		}
    286 #endif
    287 	}
    288 
    289 	if (sigfile)
    290 		{
    291 		BIO *sigbio = BIO_new_file(sigfile, "rb");
    292 		if (!sigbio)
    293 			{
    294 			BIO_printf(bio_err, "Can't open signature file %s\n",
    295 								sigfile);
    296 			goto end;
    297 			}
    298 		siglen = bio_to_mem(&sig, keysize * 10, sigbio);
    299 		BIO_free(sigbio);
    300 		if (siglen <= 0)
    301 			{
    302 			BIO_printf(bio_err, "Error reading signature data\n");
    303 			goto end;
    304 			}
    305 		}
    306 
    307 	if (in)
    308 		{
    309 		/* Read the input data */
    310 		buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
    311 		if(buf_inlen <= 0)
    312 			{
    313 			BIO_printf(bio_err, "Error reading input Data\n");
    314 			exit(1);
    315 			}
    316 		if(rev)
    317 			{
    318 			size_t i;
    319 			unsigned char ctmp;
    320 			size_t l = (size_t)buf_inlen;
    321 			for(i = 0; i < l/2; i++)
    322 				{
    323 				ctmp = buf_in[i];
    324 				buf_in[i] = buf_in[l - 1 - i];
    325 				buf_in[l - 1 - i] = ctmp;
    326 				}
    327 			}
    328 		}
    329 
    330 	if(pkey_op == EVP_PKEY_OP_VERIFY)
    331 		{
    332 		rv  = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
    333 				      buf_in, (size_t)buf_inlen);
    334 		if (rv == 0)
    335 			BIO_puts(out, "Signature Verification Failure\n");
    336 		else if (rv == 1)
    337 			BIO_puts(out, "Signature Verified Successfully\n");
    338 		if (rv >= 0)
    339 			goto end;
    340 		}
    341 	else
    342 		{
    343 		rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
    344 			      buf_in, (size_t)buf_inlen);
    345 		if (rv > 0)
    346 			{
    347 			buf_out = OPENSSL_malloc(buf_outlen);
    348 			if (!buf_out)
    349 				rv = -1;
    350 			else
    351 				rv = do_keyop(ctx, pkey_op,
    352 						buf_out, (size_t *)&buf_outlen,
    353 						buf_in, (size_t)buf_inlen);
    354 			}
    355 		}
    356 
    357 	if(rv <= 0)
    358 		{
    359 		BIO_printf(bio_err, "Public Key operation error\n");
    360 		ERR_print_errors(bio_err);
    361 		goto end;
    362 		}
    363 	ret = 0;
    364 	if(asn1parse)
    365 		{
    366 		if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
    367 			ERR_print_errors(bio_err);
    368 		}
    369 	else if(hexdump)
    370 		BIO_dump(out, (char *)buf_out, buf_outlen);
    371 	else
    372 		BIO_write(out, buf_out, buf_outlen);
    373 
    374 	end:
    375 	if (ctx)
    376 		EVP_PKEY_CTX_free(ctx);
    377 	BIO_free(in);
    378 	BIO_free_all(out);
    379 	if (buf_in)
    380 		OPENSSL_free(buf_in);
    381 	if (buf_out)
    382 		OPENSSL_free(buf_out);
    383 	if (sig)
    384 		OPENSSL_free(sig);
    385 	return ret;
    386 }
    387 
    388 static void usage()
    389 {
    390 	BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
    391 	BIO_printf(bio_err, "-in file        input file\n");
    392 	BIO_printf(bio_err, "-out file       output file\n");
    393 	BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
    394 	BIO_printf(bio_err, "-inkey file     input key\n");
    395 	BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
    396 	BIO_printf(bio_err, "-pubin          input is a public key\n");
    397 	BIO_printf(bio_err, "-certin         input is a certificate carrying a public key\n");
    398 	BIO_printf(bio_err, "-pkeyopt X:Y    public key options\n");
    399 	BIO_printf(bio_err, "-sign           sign with private key\n");
    400 	BIO_printf(bio_err, "-verify         verify with public key\n");
    401 	BIO_printf(bio_err, "-verifyrecover  verify with public key, recover original data\n");
    402 	BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
    403 	BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
    404 	BIO_printf(bio_err, "-derive         derive shared secret\n");
    405 	BIO_printf(bio_err, "-hexdump        hex dump output\n");
    406 #ifndef OPENSSL_NO_ENGINE
    407 	BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
    408 #endif
    409 	BIO_printf(bio_err, "-passin arg     pass phrase source\n");
    410 
    411 }
    412 
    413 static EVP_PKEY_CTX *init_ctx(int *pkeysize,
    414 				char *keyfile, int keyform, int key_type,
    415 				char *passargin, int pkey_op, ENGINE *e)
    416 	{
    417 	EVP_PKEY *pkey = NULL;
    418 	EVP_PKEY_CTX *ctx = NULL;
    419 	char *passin = NULL;
    420 	int rv = -1;
    421 	X509 *x;
    422 	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
    423 		|| (pkey_op == EVP_PKEY_OP_DERIVE))
    424 		&& (key_type != KEY_PRIVKEY))
    425 		{
    426 		BIO_printf(bio_err, "A private key is needed for this operation\n");
    427 		goto end;
    428 		}
    429 	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
    430 		{
    431 		BIO_printf(bio_err, "Error getting password\n");
    432 		goto end;
    433 		}
    434 	switch(key_type)
    435 		{
    436 		case KEY_PRIVKEY:
    437 		pkey = load_key(bio_err, keyfile, keyform, 0,
    438 			passin, e, "Private Key");
    439 		break;
    440 
    441 		case KEY_PUBKEY:
    442 		pkey = load_pubkey(bio_err, keyfile, keyform, 0,
    443 			NULL, e, "Public Key");
    444 		break;
    445 
    446 		case KEY_CERT:
    447 		x = load_cert(bio_err, keyfile, keyform,
    448 			NULL, e, "Certificate");
    449 		if(x)
    450 			{
    451 			pkey = X509_get_pubkey(x);
    452 			X509_free(x);
    453 			}
    454 		break;
    455 
    456 		}
    457 
    458 	*pkeysize = EVP_PKEY_size(pkey);
    459 
    460 	if (!pkey)
    461 		goto end;
    462 
    463 	ctx = EVP_PKEY_CTX_new(pkey, e);
    464 
    465 	EVP_PKEY_free(pkey);
    466 
    467 	if (!ctx)
    468 		goto end;
    469 
    470 	switch(pkey_op)
    471 		{
    472 		case EVP_PKEY_OP_SIGN:
    473 		rv = EVP_PKEY_sign_init(ctx);
    474 		break;
    475 
    476 		case EVP_PKEY_OP_VERIFY:
    477 		rv = EVP_PKEY_verify_init(ctx);
    478 		break;
    479 
    480 		case EVP_PKEY_OP_VERIFYRECOVER:
    481 		rv = EVP_PKEY_verify_recover_init(ctx);
    482 		break;
    483 
    484 		case EVP_PKEY_OP_ENCRYPT:
    485 		rv = EVP_PKEY_encrypt_init(ctx);
    486 		break;
    487 
    488 		case EVP_PKEY_OP_DECRYPT:
    489 		rv = EVP_PKEY_decrypt_init(ctx);
    490 		break;
    491 
    492 		case EVP_PKEY_OP_DERIVE:
    493 		rv = EVP_PKEY_derive_init(ctx);
    494 		break;
    495 		}
    496 
    497 	if (rv <= 0)
    498 		{
    499 		EVP_PKEY_CTX_free(ctx);
    500 		ctx = NULL;
    501 		}
    502 
    503 	end:
    504 
    505 	if (passin)
    506 		OPENSSL_free(passin);
    507 
    508 	return ctx;
    509 
    510 
    511 	}
    512 
    513 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
    514 							const char *file)
    515 	{
    516 	EVP_PKEY *peer = NULL;
    517 	int ret;
    518 	if (!ctx)
    519 		{
    520 		BIO_puts(err, "-peerkey command before -inkey\n");
    521 		return 0;
    522 		}
    523 
    524 	peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
    525 
    526 	if (!peer)
    527 		{
    528 		BIO_printf(bio_err, "Error reading peer key %s\n", file);
    529 		ERR_print_errors(err);
    530 		return 0;
    531 		}
    532 
    533 	ret = EVP_PKEY_derive_set_peer(ctx, peer);
    534 
    535 	EVP_PKEY_free(peer);
    536 	if (ret <= 0)
    537 		ERR_print_errors(err);
    538 	return ret;
    539 	}
    540 
    541 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
    542 		unsigned char *out, size_t *poutlen,
    543 		unsigned char *in, size_t inlen)
    544 	{
    545 	int rv = 0;
    546 	switch(pkey_op)
    547 		{
    548 		case EVP_PKEY_OP_VERIFYRECOVER:
    549 		rv  = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
    550 		break;
    551 
    552 		case EVP_PKEY_OP_SIGN:
    553 		rv  = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
    554 		break;
    555 
    556 		case EVP_PKEY_OP_ENCRYPT:
    557 		rv  = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
    558 		break;
    559 
    560 		case EVP_PKEY_OP_DECRYPT:
    561 		rv  = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
    562 		break;
    563 
    564 		case EVP_PKEY_OP_DERIVE:
    565 		rv  = EVP_PKEY_derive(ctx, out, poutlen);
    566 		break;
    567 
    568 		}
    569 	return rv;
    570 	}
    571