1238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2238384Sjkim * project 2006.
3238384Sjkim */
4238384Sjkim/* ====================================================================
5238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6238384Sjkim *
7238384Sjkim * Redistribution and use in source and binary forms, with or without
8238384Sjkim * modification, are permitted provided that the following conditions
9238384Sjkim * are met:
10238384Sjkim *
11238384Sjkim * 1. Redistributions of source code must retain the above copyright
12238384Sjkim *    notice, this list of conditions and the following disclaimer.
13238384Sjkim *
14238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
15238384Sjkim *    notice, this list of conditions and the following disclaimer in
16238384Sjkim *    the documentation and/or other materials provided with the
17238384Sjkim *    distribution.
18238384Sjkim *
19238384Sjkim * 3. All advertising materials mentioning features or use of this
20238384Sjkim *    software must display the following acknowledgment:
21238384Sjkim *    "This product includes software developed by the OpenSSL Project
22238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23238384Sjkim *
24238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25238384Sjkim *    endorse or promote products derived from this software without
26238384Sjkim *    prior written permission. For written permission, please contact
27238384Sjkim *    licensing@OpenSSL.org.
28238384Sjkim *
29238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
30238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
31238384Sjkim *    permission of the OpenSSL Project.
32238384Sjkim *
33238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
34238384Sjkim *    acknowledgment:
35238384Sjkim *    "This product includes software developed by the OpenSSL Project
36238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37238384Sjkim *
38238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
50238384Sjkim * ====================================================================
51238384Sjkim *
52238384Sjkim * This product includes cryptographic software written by Eric Young
53238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
54238384Sjkim * Hudson (tjh@cryptsoft.com).
55238384Sjkim *
56238384Sjkim */
57238384Sjkim
58238384Sjkim
59238384Sjkim#include "apps.h"
60238384Sjkim#include <string.h>
61238384Sjkim#include <openssl/err.h>
62238384Sjkim#include <openssl/pem.h>
63238384Sjkim#include <openssl/evp.h>
64238384Sjkim
65238384Sjkim#define KEY_PRIVKEY	1
66238384Sjkim#define KEY_PUBKEY	2
67238384Sjkim#define KEY_CERT	3
68238384Sjkim
69238384Sjkimstatic void usage(void);
70238384Sjkim
71238384Sjkim#undef PROG
72238384Sjkim
73238384Sjkim#define PROG pkeyutl_main
74238384Sjkim
75238384Sjkimstatic EVP_PKEY_CTX *init_ctx(int *pkeysize,
76238384Sjkim				char *keyfile, int keyform, int key_type,
77238384Sjkim				char *passargin, int pkey_op, ENGINE *e);
78238384Sjkim
79238384Sjkimstatic int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
80238384Sjkim							const char *file);
81238384Sjkim
82238384Sjkimstatic int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
83238384Sjkim		unsigned char *out, size_t *poutlen,
84238384Sjkim		unsigned char *in, size_t inlen);
85238384Sjkim
86238384Sjkimint MAIN(int argc, char **);
87238384Sjkim
88238384Sjkimint MAIN(int argc, char **argv)
89238384Sjkim{
90238384Sjkim	BIO *in = NULL, *out = NULL;
91238384Sjkim	char *infile = NULL, *outfile = NULL, *sigfile = NULL;
92238384Sjkim	ENGINE *e = NULL;
93238384Sjkim	int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
94238384Sjkim	int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
95238384Sjkim	char badarg = 0, rev = 0;
96238384Sjkim	char hexdump = 0, asn1parse = 0;
97238384Sjkim	EVP_PKEY_CTX *ctx = NULL;
98238384Sjkim	char *passargin = NULL;
99238384Sjkim	int keysize = -1;
100238384Sjkim
101238384Sjkim	unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
102238384Sjkim	size_t buf_outlen;
103238384Sjkim	int buf_inlen = 0, siglen = -1;
104238384Sjkim
105238384Sjkim	int ret = 1, rv = -1;
106238384Sjkim
107238384Sjkim	argc--;
108238384Sjkim	argv++;
109238384Sjkim
110238384Sjkim	if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
111238384Sjkim
112238384Sjkim	if (!load_config(bio_err, NULL))
113238384Sjkim		goto end;
114238384Sjkim	ERR_load_crypto_strings();
115238384Sjkim	OpenSSL_add_all_algorithms();
116238384Sjkim
117238384Sjkim	while(argc >= 1)
118238384Sjkim		{
119238384Sjkim		if (!strcmp(*argv,"-in"))
120238384Sjkim			{
121238384Sjkim			if (--argc < 1) badarg = 1;
122238384Sjkim                        else infile= *(++argv);
123238384Sjkim			}
124238384Sjkim		else if (!strcmp(*argv,"-out"))
125238384Sjkim			{
126238384Sjkim			if (--argc < 1) badarg = 1;
127238384Sjkim			else outfile= *(++argv);
128238384Sjkim			}
129238384Sjkim		else if (!strcmp(*argv,"-sigfile"))
130238384Sjkim			{
131238384Sjkim			if (--argc < 1) badarg = 1;
132238384Sjkim			else sigfile= *(++argv);
133238384Sjkim			}
134238384Sjkim		else if(!strcmp(*argv, "-inkey"))
135238384Sjkim			{
136238384Sjkim			if (--argc < 1)
137238384Sjkim				badarg = 1;
138238384Sjkim			else
139238384Sjkim				{
140238384Sjkim				ctx = init_ctx(&keysize,
141238384Sjkim						*(++argv), keyform, key_type,
142238384Sjkim						passargin, pkey_op, e);
143238384Sjkim				if (!ctx)
144238384Sjkim					{
145238384Sjkim					BIO_puts(bio_err,
146238384Sjkim						"Error initializing context\n");
147238384Sjkim					ERR_print_errors(bio_err);
148238384Sjkim					badarg = 1;
149238384Sjkim					}
150238384Sjkim				}
151238384Sjkim			}
152238384Sjkim		else if (!strcmp(*argv,"-peerkey"))
153238384Sjkim			{
154238384Sjkim			if (--argc < 1)
155238384Sjkim				badarg = 1;
156238384Sjkim			else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
157238384Sjkim				badarg = 1;
158238384Sjkim			}
159238384Sjkim		else if (!strcmp(*argv,"-passin"))
160238384Sjkim			{
161238384Sjkim			if (--argc < 1) badarg = 1;
162238384Sjkim			else passargin= *(++argv);
163238384Sjkim			}
164238384Sjkim		else if (strcmp(*argv,"-peerform") == 0)
165238384Sjkim			{
166238384Sjkim			if (--argc < 1) badarg = 1;
167238384Sjkim			else peerform=str2fmt(*(++argv));
168238384Sjkim			}
169238384Sjkim		else if (strcmp(*argv,"-keyform") == 0)
170238384Sjkim			{
171238384Sjkim			if (--argc < 1) badarg = 1;
172238384Sjkim			else keyform=str2fmt(*(++argv));
173238384Sjkim			}
174238384Sjkim#ifndef OPENSSL_NO_ENGINE
175238384Sjkim		else if(!strcmp(*argv, "-engine"))
176238384Sjkim			{
177238384Sjkim			if (--argc < 1)
178238384Sjkim				badarg = 1;
179238384Sjkim			else
180238384Sjkim				e = setup_engine(bio_err, *(++argv), 0);
181238384Sjkim			}
182238384Sjkim#endif
183238384Sjkim		else if(!strcmp(*argv, "-pubin"))
184238384Sjkim			key_type = KEY_PUBKEY;
185238384Sjkim		else if(!strcmp(*argv, "-certin"))
186238384Sjkim			key_type = KEY_CERT;
187238384Sjkim		else if(!strcmp(*argv, "-asn1parse"))
188238384Sjkim			asn1parse = 1;
189238384Sjkim		else if(!strcmp(*argv, "-hexdump"))
190238384Sjkim			hexdump = 1;
191238384Sjkim		else if(!strcmp(*argv, "-sign"))
192238384Sjkim			pkey_op = EVP_PKEY_OP_SIGN;
193238384Sjkim		else if(!strcmp(*argv, "-verify"))
194238384Sjkim			pkey_op = EVP_PKEY_OP_VERIFY;
195238384Sjkim		else if(!strcmp(*argv, "-verifyrecover"))
196238384Sjkim			pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
197238384Sjkim		else if(!strcmp(*argv, "-rev"))
198238384Sjkim			rev = 1;
199238384Sjkim		else if(!strcmp(*argv, "-encrypt"))
200238384Sjkim			pkey_op = EVP_PKEY_OP_ENCRYPT;
201238384Sjkim		else if(!strcmp(*argv, "-decrypt"))
202238384Sjkim			pkey_op = EVP_PKEY_OP_DECRYPT;
203238384Sjkim		else if(!strcmp(*argv, "-derive"))
204238384Sjkim			pkey_op = EVP_PKEY_OP_DERIVE;
205238384Sjkim		else if (strcmp(*argv,"-pkeyopt") == 0)
206238384Sjkim			{
207238384Sjkim			if (--argc < 1)
208238384Sjkim				badarg = 1;
209238384Sjkim			else if (!ctx)
210238384Sjkim				{
211238384Sjkim				BIO_puts(bio_err,
212238384Sjkim					"-pkeyopt command before -inkey\n");
213238384Sjkim				badarg = 1;
214238384Sjkim				}
215238384Sjkim			else if (pkey_ctrl_string(ctx, *(++argv)) <= 0)
216238384Sjkim				{
217238384Sjkim				BIO_puts(bio_err, "parameter setting error\n");
218238384Sjkim				ERR_print_errors(bio_err);
219238384Sjkim				goto end;
220238384Sjkim				}
221238384Sjkim			}
222238384Sjkim		else badarg = 1;
223238384Sjkim		if(badarg)
224238384Sjkim			{
225238384Sjkim			usage();
226238384Sjkim			goto end;
227238384Sjkim			}
228238384Sjkim		argc--;
229238384Sjkim		argv++;
230238384Sjkim		}
231238384Sjkim
232238384Sjkim	if (!ctx)
233238384Sjkim		{
234238384Sjkim		usage();
235238384Sjkim		goto end;
236238384Sjkim		}
237238384Sjkim
238238384Sjkim	if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY))
239238384Sjkim		{
240238384Sjkim		BIO_puts(bio_err, "Signature file specified for non verify\n");
241238384Sjkim		goto end;
242238384Sjkim		}
243238384Sjkim
244238384Sjkim	if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY))
245238384Sjkim		{
246238384Sjkim		BIO_puts(bio_err, "No signature file specified for verify\n");
247238384Sjkim		goto end;
248238384Sjkim		}
249238384Sjkim
250238384Sjkim/* FIXME: seed PRNG only if needed */
251238384Sjkim	app_RAND_load_file(NULL, bio_err, 0);
252238384Sjkim
253238384Sjkim	if (pkey_op != EVP_PKEY_OP_DERIVE)
254238384Sjkim		{
255238384Sjkim		if(infile)
256238384Sjkim			{
257238384Sjkim			if(!(in = BIO_new_file(infile, "rb")))
258238384Sjkim				{
259238384Sjkim				BIO_puts(bio_err,
260238384Sjkim					"Error Opening Input File\n");
261238384Sjkim				ERR_print_errors(bio_err);
262238384Sjkim				goto end;
263238384Sjkim				}
264238384Sjkim			}
265238384Sjkim		else
266238384Sjkim			in = BIO_new_fp(stdin, BIO_NOCLOSE);
267238384Sjkim		}
268238384Sjkim
269238384Sjkim	if(outfile)
270238384Sjkim		{
271238384Sjkim		if(!(out = BIO_new_file(outfile, "wb")))
272238384Sjkim			{
273238384Sjkim			BIO_printf(bio_err, "Error Creating Output File\n");
274238384Sjkim			ERR_print_errors(bio_err);
275238384Sjkim			goto end;
276238384Sjkim			}
277238384Sjkim		}
278238384Sjkim	else
279238384Sjkim		{
280238384Sjkim		out = BIO_new_fp(stdout, BIO_NOCLOSE);
281238384Sjkim#ifdef OPENSSL_SYS_VMS
282238384Sjkim		{
283238384Sjkim		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
284238384Sjkim		    out = BIO_push(tmpbio, out);
285238384Sjkim		}
286238384Sjkim#endif
287238384Sjkim	}
288238384Sjkim
289238384Sjkim	if (sigfile)
290238384Sjkim		{
291238384Sjkim		BIO *sigbio = BIO_new_file(sigfile, "rb");
292238384Sjkim		if (!sigbio)
293238384Sjkim			{
294238384Sjkim			BIO_printf(bio_err, "Can't open signature file %s\n",
295238384Sjkim								sigfile);
296238384Sjkim			goto end;
297238384Sjkim			}
298238384Sjkim		siglen = bio_to_mem(&sig, keysize * 10, sigbio);
299238384Sjkim		BIO_free(sigbio);
300238384Sjkim		if (siglen <= 0)
301238384Sjkim			{
302238384Sjkim			BIO_printf(bio_err, "Error reading signature data\n");
303238384Sjkim			goto end;
304238384Sjkim			}
305238384Sjkim		}
306238384Sjkim
307238384Sjkim	if (in)
308238384Sjkim		{
309238384Sjkim		/* Read the input data */
310238384Sjkim		buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
311238384Sjkim		if(buf_inlen <= 0)
312238384Sjkim			{
313238384Sjkim			BIO_printf(bio_err, "Error reading input Data\n");
314238384Sjkim			exit(1);
315238384Sjkim			}
316238384Sjkim		if(rev)
317238384Sjkim			{
318238384Sjkim			size_t i;
319238384Sjkim			unsigned char ctmp;
320238384Sjkim			size_t l = (size_t)buf_inlen;
321238384Sjkim			for(i = 0; i < l/2; i++)
322238384Sjkim				{
323238384Sjkim				ctmp = buf_in[i];
324238384Sjkim				buf_in[i] = buf_in[l - 1 - i];
325238384Sjkim				buf_in[l - 1 - i] = ctmp;
326238384Sjkim				}
327238384Sjkim			}
328238384Sjkim		}
329238384Sjkim
330238384Sjkim	if(pkey_op == EVP_PKEY_OP_VERIFY)
331238384Sjkim		{
332238384Sjkim		rv  = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
333238384Sjkim				      buf_in, (size_t)buf_inlen);
334238384Sjkim		if (rv == 0)
335238384Sjkim			BIO_puts(out, "Signature Verification Failure\n");
336238384Sjkim		else if (rv == 1)
337238384Sjkim			BIO_puts(out, "Signature Verified Successfully\n");
338238384Sjkim		if (rv >= 0)
339238384Sjkim			goto end;
340238384Sjkim		}
341238384Sjkim	else
342238384Sjkim		{
343238384Sjkim		rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
344238384Sjkim			      buf_in, (size_t)buf_inlen);
345238384Sjkim		if (rv > 0)
346238384Sjkim			{
347238384Sjkim			buf_out = OPENSSL_malloc(buf_outlen);
348238384Sjkim			if (!buf_out)
349238384Sjkim				rv = -1;
350238384Sjkim			else
351238384Sjkim				rv = do_keyop(ctx, pkey_op,
352238384Sjkim						buf_out, (size_t *)&buf_outlen,
353238384Sjkim						buf_in, (size_t)buf_inlen);
354238384Sjkim			}
355238384Sjkim		}
356238384Sjkim
357238384Sjkim	if(rv <= 0)
358238384Sjkim		{
359238384Sjkim		BIO_printf(bio_err, "Public Key operation error\n");
360238384Sjkim		ERR_print_errors(bio_err);
361238384Sjkim		goto end;
362238384Sjkim		}
363238384Sjkim	ret = 0;
364238384Sjkim	if(asn1parse)
365238384Sjkim		{
366238384Sjkim		if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
367238384Sjkim			ERR_print_errors(bio_err);
368238384Sjkim		}
369238384Sjkim	else if(hexdump)
370238384Sjkim		BIO_dump(out, (char *)buf_out, buf_outlen);
371238384Sjkim	else
372238384Sjkim		BIO_write(out, buf_out, buf_outlen);
373238384Sjkim
374238384Sjkim	end:
375238384Sjkim	if (ctx)
376238384Sjkim		EVP_PKEY_CTX_free(ctx);
377238384Sjkim	BIO_free(in);
378238384Sjkim	BIO_free_all(out);
379238384Sjkim	if (buf_in)
380238384Sjkim		OPENSSL_free(buf_in);
381238384Sjkim	if (buf_out)
382238384Sjkim		OPENSSL_free(buf_out);
383238384Sjkim	if (sig)
384238384Sjkim		OPENSSL_free(sig);
385238384Sjkim	return ret;
386238384Sjkim}
387238384Sjkim
388238384Sjkimstatic void usage()
389238384Sjkim{
390238384Sjkim	BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
391238384Sjkim	BIO_printf(bio_err, "-in file        input file\n");
392238384Sjkim	BIO_printf(bio_err, "-out file       output file\n");
393238384Sjkim	BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
394238384Sjkim	BIO_printf(bio_err, "-inkey file     input key\n");
395238384Sjkim	BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
396238384Sjkim	BIO_printf(bio_err, "-pubin          input is a public key\n");
397238384Sjkim	BIO_printf(bio_err, "-certin         input is a certificate carrying a public key\n");
398238384Sjkim	BIO_printf(bio_err, "-pkeyopt X:Y    public key options\n");
399238384Sjkim	BIO_printf(bio_err, "-sign           sign with private key\n");
400238384Sjkim	BIO_printf(bio_err, "-verify         verify with public key\n");
401238384Sjkim	BIO_printf(bio_err, "-verifyrecover  verify with public key, recover original data\n");
402238384Sjkim	BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
403238384Sjkim	BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
404238384Sjkim	BIO_printf(bio_err, "-derive         derive shared secret\n");
405238384Sjkim	BIO_printf(bio_err, "-hexdump        hex dump output\n");
406238384Sjkim#ifndef OPENSSL_NO_ENGINE
407238384Sjkim	BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
408238384Sjkim#endif
409238384Sjkim	BIO_printf(bio_err, "-passin arg     pass phrase source\n");
410238384Sjkim
411238384Sjkim}
412238384Sjkim
413238384Sjkimstatic EVP_PKEY_CTX *init_ctx(int *pkeysize,
414238384Sjkim				char *keyfile, int keyform, int key_type,
415238384Sjkim				char *passargin, int pkey_op, ENGINE *e)
416238384Sjkim	{
417238384Sjkim	EVP_PKEY *pkey = NULL;
418238384Sjkim	EVP_PKEY_CTX *ctx = NULL;
419238384Sjkim	char *passin = NULL;
420238384Sjkim	int rv = -1;
421238384Sjkim	X509 *x;
422238384Sjkim	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
423238384Sjkim		|| (pkey_op == EVP_PKEY_OP_DERIVE))
424238384Sjkim		&& (key_type != KEY_PRIVKEY))
425238384Sjkim		{
426238384Sjkim		BIO_printf(bio_err, "A private key is needed for this operation\n");
427238384Sjkim		goto end;
428238384Sjkim		}
429238384Sjkim	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
430238384Sjkim		{
431238384Sjkim		BIO_printf(bio_err, "Error getting password\n");
432238384Sjkim		goto end;
433238384Sjkim		}
434238384Sjkim	switch(key_type)
435238384Sjkim		{
436238384Sjkim		case KEY_PRIVKEY:
437238384Sjkim		pkey = load_key(bio_err, keyfile, keyform, 0,
438238384Sjkim			passin, e, "Private Key");
439238384Sjkim		break;
440238384Sjkim
441238384Sjkim		case KEY_PUBKEY:
442238384Sjkim		pkey = load_pubkey(bio_err, keyfile, keyform, 0,
443238384Sjkim			NULL, e, "Public Key");
444238384Sjkim		break;
445238384Sjkim
446238384Sjkim		case KEY_CERT:
447238384Sjkim		x = load_cert(bio_err, keyfile, keyform,
448238384Sjkim			NULL, e, "Certificate");
449238384Sjkim		if(x)
450238384Sjkim			{
451238384Sjkim			pkey = X509_get_pubkey(x);
452238384Sjkim			X509_free(x);
453238384Sjkim			}
454238384Sjkim		break;
455238384Sjkim
456238384Sjkim		}
457238384Sjkim
458238384Sjkim	*pkeysize = EVP_PKEY_size(pkey);
459238384Sjkim
460238384Sjkim	if (!pkey)
461238384Sjkim		goto end;
462238384Sjkim
463238384Sjkim	ctx = EVP_PKEY_CTX_new(pkey, e);
464238384Sjkim
465238384Sjkim	EVP_PKEY_free(pkey);
466238384Sjkim
467238384Sjkim	if (!ctx)
468238384Sjkim		goto end;
469238384Sjkim
470238384Sjkim	switch(pkey_op)
471238384Sjkim		{
472238384Sjkim		case EVP_PKEY_OP_SIGN:
473238384Sjkim		rv = EVP_PKEY_sign_init(ctx);
474238384Sjkim		break;
475238384Sjkim
476238384Sjkim		case EVP_PKEY_OP_VERIFY:
477238384Sjkim		rv = EVP_PKEY_verify_init(ctx);
478238384Sjkim		break;
479238384Sjkim
480238384Sjkim		case EVP_PKEY_OP_VERIFYRECOVER:
481238384Sjkim		rv = EVP_PKEY_verify_recover_init(ctx);
482238384Sjkim		break;
483238384Sjkim
484238384Sjkim		case EVP_PKEY_OP_ENCRYPT:
485238384Sjkim		rv = EVP_PKEY_encrypt_init(ctx);
486238384Sjkim		break;
487238384Sjkim
488238384Sjkim		case EVP_PKEY_OP_DECRYPT:
489238384Sjkim		rv = EVP_PKEY_decrypt_init(ctx);
490238384Sjkim		break;
491238384Sjkim
492238384Sjkim		case EVP_PKEY_OP_DERIVE:
493238384Sjkim		rv = EVP_PKEY_derive_init(ctx);
494238384Sjkim		break;
495238384Sjkim		}
496238384Sjkim
497238384Sjkim	if (rv <= 0)
498238384Sjkim		{
499238384Sjkim		EVP_PKEY_CTX_free(ctx);
500238384Sjkim		ctx = NULL;
501238384Sjkim		}
502238384Sjkim
503238384Sjkim	end:
504238384Sjkim
505238384Sjkim	if (passin)
506238384Sjkim		OPENSSL_free(passin);
507238384Sjkim
508238384Sjkim	return ctx;
509238384Sjkim
510238384Sjkim
511238384Sjkim	}
512238384Sjkim
513238384Sjkimstatic int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
514238384Sjkim							const char *file)
515238384Sjkim	{
516238384Sjkim	EVP_PKEY *peer = NULL;
517238384Sjkim	int ret;
518238384Sjkim	if (!ctx)
519238384Sjkim		{
520238384Sjkim		BIO_puts(err, "-peerkey command before -inkey\n");
521238384Sjkim		return 0;
522238384Sjkim		}
523238384Sjkim
524238384Sjkim	peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
525238384Sjkim
526238384Sjkim	if (!peer)
527238384Sjkim		{
528238384Sjkim		BIO_printf(bio_err, "Error reading peer key %s\n", file);
529238384Sjkim		ERR_print_errors(err);
530238384Sjkim		return 0;
531238384Sjkim		}
532238384Sjkim
533238384Sjkim	ret = EVP_PKEY_derive_set_peer(ctx, peer);
534238384Sjkim
535238384Sjkim	EVP_PKEY_free(peer);
536238384Sjkim	if (ret <= 0)
537238384Sjkim		ERR_print_errors(err);
538238384Sjkim	return ret;
539238384Sjkim	}
540238384Sjkim
541238384Sjkimstatic int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
542238384Sjkim		unsigned char *out, size_t *poutlen,
543238384Sjkim		unsigned char *in, size_t inlen)
544238384Sjkim	{
545238384Sjkim	int rv = 0;
546238384Sjkim	switch(pkey_op)
547238384Sjkim		{
548238384Sjkim		case EVP_PKEY_OP_VERIFYRECOVER:
549238384Sjkim		rv  = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
550238384Sjkim		break;
551238384Sjkim
552238384Sjkim		case EVP_PKEY_OP_SIGN:
553238384Sjkim		rv  = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
554238384Sjkim		break;
555238384Sjkim
556238384Sjkim		case EVP_PKEY_OP_ENCRYPT:
557238384Sjkim		rv  = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
558238384Sjkim		break;
559238384Sjkim
560238384Sjkim		case EVP_PKEY_OP_DECRYPT:
561238384Sjkim		rv  = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
562238384Sjkim		break;
563238384Sjkim
564238384Sjkim		case EVP_PKEY_OP_DERIVE:
565238384Sjkim		rv  = EVP_PKEY_derive(ctx, out, poutlen);
566238384Sjkim		break;
567238384Sjkim
568238384Sjkim		}
569238384Sjkim	return rv;
570238384Sjkim	}
571