1480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * project 2006.
3480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org */
4480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* ====================================================================
5480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
7480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * Redistribution and use in source and binary forms, with or without
8480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * modification, are permitted provided that the following conditions
9480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * are met:
10480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
11480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 1. Redistributions of source code must retain the above copyright
12480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    notice, this list of conditions and the following disclaimer.
13480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
14480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
15480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    notice, this list of conditions and the following disclaimer in
16480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    the documentation and/or other materials provided with the
17480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    distribution.
18480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
19480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 3. All advertising materials mentioning features or use of this
20480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    software must display the following acknowledgment:
21480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    "This product includes software developed by the OpenSSL Project
22480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
24480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    endorse or promote products derived from this software without
26480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    prior written permission. For written permission, please contact
27480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    licensing@OpenSSL.org.
28480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
29480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 5. Products derived from this software may not be called "OpenSSL"
30480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    nor may "OpenSSL" appear in their names without prior written
31480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    permission of the OpenSSL Project.
32480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
33480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * 6. Redistributions of any form whatsoever must retain the following
34480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    acknowledgment:
35480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    "This product includes software developed by the OpenSSL Project
36480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
38480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
50480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * ====================================================================
51480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
52480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * This product includes cryptographic software written by Eric Young
53480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * (eay@cryptsoft.com).  This product includes software written by Tim
54480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org * Hudson (tjh@cryptsoft.com).
55480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org *
56480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org */
57480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
58480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
59480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include "apps.h"
60480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <string.h>
61480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/err.h>
62480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/pem.h>
63480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#include <openssl/evp.h>
64480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
65480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#define KEY_PRIVKEY	1
66480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#define KEY_PUBKEY	2
67480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#define KEY_CERT	3
68480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
69480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic void usage(void);
70480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
71480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#undef PROG
72480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
73480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#define PROG pkeyutl_main
74480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
75480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic EVP_PKEY_CTX *init_ctx(int *pkeysize,
76480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				char *keyfile, int keyform, int key_type,
77480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				char *passargin, int pkey_op, ENGINE *e);
78480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
79480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
80480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							const char *file);
81480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
82480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
83480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		unsigned char *out, size_t *poutlen,
84480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		unsigned char *in, size_t inlen);
85480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
86480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgint MAIN(int argc, char **);
87480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
88480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgint MAIN(int argc, char **argv)
89480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org{
90480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO *in = NULL, *out = NULL;
91480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	char *infile = NULL, *outfile = NULL, *sigfile = NULL;
92480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ENGINE *e = NULL;
93480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
94480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
95480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	char badarg = 0, rev = 0;
96480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	char hexdump = 0, asn1parse = 0;
97480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_CTX *ctx = NULL;
98480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	char *passargin = NULL;
99480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int keysize = -1;
100480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
101480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
102480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	size_t buf_outlen;
103480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int buf_inlen = 0, siglen = -1;
104480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
105480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret = 1, rv = -1;
106480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
107480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	argc--;
108480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	argv++;
109480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
110480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(!bio_err) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
111480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
112480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!load_config(bio_err, NULL))
113480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
114480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ERR_load_crypto_strings();
115480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	OpenSSL_add_all_algorithms();
116480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
117480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	while(argc >= 1)
118480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
119480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!strcmp(*argv,"-in"))
120480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
121480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1) badarg = 1;
122480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org                        else infile= *(++argv);
123480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
124480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(*argv,"-out"))
125480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
126480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1) badarg = 1;
127480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else outfile= *(++argv);
128480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
129480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(*argv,"-sigfile"))
130480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
131480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1) badarg = 1;
132480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else sigfile= *(++argv);
133480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
134480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-inkey"))
135480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
136480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1)
137480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				badarg = 1;
138480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else
139480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
140480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ctx = init_ctx(&keysize,
141480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						*(++argv), keyform, key_type,
142480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						passargin, pkey_op, e);
143480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				if (!ctx)
144480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					{
145480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					BIO_puts(bio_err,
146480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						"Error initializing context\n");
147480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					ERR_print_errors(bio_err);
148480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					badarg = 1;
149480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					}
150480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
151480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
152480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(*argv,"-peerkey"))
153480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
154480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1)
155480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				badarg = 1;
156480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
157480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				badarg = 1;
158480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
159480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (!strcmp(*argv,"-passin"))
160480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
161480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1) badarg = 1;
162480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else passargin= *(++argv);
163480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
164480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (strcmp(*argv,"-peerform") == 0)
165480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
166480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1) badarg = 1;
167480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else peerform=str2fmt(*(++argv));
168480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
169480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (strcmp(*argv,"-keyform") == 0)
170480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
171480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1) badarg = 1;
172480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else keyform=str2fmt(*(++argv));
173480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
174480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#ifndef OPENSSL_NO_ENGINE
175480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-engine"))
176480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
177480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1)
178480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				badarg = 1;
179480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else
180480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				e = setup_engine(bio_err, *(++argv), 0);
181480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
182480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
183480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-pubin"))
184480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			key_type = KEY_PUBKEY;
185480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-certin"))
186480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			key_type = KEY_CERT;
187480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-asn1parse"))
188480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			asn1parse = 1;
189480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-hexdump"))
190480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			hexdump = 1;
191480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-sign"))
192480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey_op = EVP_PKEY_OP_SIGN;
193480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-verify"))
194480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey_op = EVP_PKEY_OP_VERIFY;
195480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-verifyrecover"))
196480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
197480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-rev"))
198480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			rev = 1;
199480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-encrypt"))
200480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey_op = EVP_PKEY_OP_ENCRYPT;
201480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-decrypt"))
202480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey_op = EVP_PKEY_OP_DECRYPT;
203480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if(!strcmp(*argv, "-derive"))
204480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey_op = EVP_PKEY_OP_DERIVE;
205480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (strcmp(*argv,"-pkeyopt") == 0)
206480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
207480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (--argc < 1)
208480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				badarg = 1;
209480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else if (!ctx)
210480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
211480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				BIO_puts(bio_err,
212480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					"-pkeyopt command before -inkey\n");
213480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				badarg = 1;
214480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
215480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else if (pkey_ctrl_string(ctx, *(++argv)) <= 0)
216480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
217480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				BIO_puts(bio_err, "parameter setting error\n");
218480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ERR_print_errors(bio_err);
219480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto end;
220480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
221480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
222480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else badarg = 1;
223480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(badarg)
224480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
225480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			usage();
226480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			goto end;
227480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
228480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		argc--;
229480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		argv++;
230480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
231480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
232480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!ctx)
233480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
234480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		usage();
235480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
236480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
237480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
238480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY))
239480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
240480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_puts(bio_err, "Signature file specified for non verify\n");
241480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
242480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
243480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
244480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY))
245480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
246480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_puts(bio_err, "No signature file specified for verify\n");
247480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
248480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
249480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
250480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org/* FIXME: seed PRNG only if needed */
251480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	app_RAND_load_file(NULL, bio_err, 0);
252480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
253480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (pkey_op != EVP_PKEY_OP_DERIVE)
254480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
255480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(infile)
256480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
257480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if(!(in = BIO_new_file(infile, "rb")))
258480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
259480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				BIO_puts(bio_err,
260480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					"Error Opening Input File\n");
261480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ERR_print_errors(bio_err);
262480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto end;
263480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
264480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
265480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else
266480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			in = BIO_new_fp(stdin, BIO_NOCLOSE);
267480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
268480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
269480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(outfile)
270480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
271480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(!(out = BIO_new_file(outfile, "wb")))
272480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
273480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_printf(bio_err, "Error Creating Output File\n");
274480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ERR_print_errors(bio_err);
275480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			goto end;
276480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
277480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
278480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
279480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
280480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		out = BIO_new_fp(stdout, BIO_NOCLOSE);
281480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#ifdef OPENSSL_SYS_VMS
282480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
283480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
284480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		    out = BIO_push(tmpbio, out);
285480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
286480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
287480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
288480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
289480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (sigfile)
290480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
291480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO *sigbio = BIO_new_file(sigfile, "rb");
292480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!sigbio)
293480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
294480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_printf(bio_err, "Can't open signature file %s\n",
295480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org								sigfile);
296480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			goto end;
297480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
298480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		siglen = bio_to_mem(&sig, keysize * 10, sigbio);
299480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_free(sigbio);
300480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (siglen <= 0)
301480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
302480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_printf(bio_err, "Error reading signature data\n");
303480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			goto end;
304480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
305480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
306480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
307480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (in)
308480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
309480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		/* Read the input data */
310480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
311480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(buf_inlen <= 0)
312480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
313480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_printf(bio_err, "Error reading input Data\n");
314480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			exit(1);
315480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
316480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(rev)
317480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
318480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			size_t i;
319480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			unsigned char ctmp;
320480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			size_t l = (size_t)buf_inlen;
321480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			for(i = 0; i < l/2; i++)
322480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
323480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ctmp = buf_in[i];
324480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				buf_in[i] = buf_in[l - 1 - i];
325480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				buf_in[l - 1 - i] = ctmp;
326480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
327480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
328480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
329480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
330480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(pkey_op == EVP_PKEY_OP_VERIFY)
331480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
332480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv  = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
333480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				      buf_in, (size_t)buf_inlen);
334480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rv == 0)
335480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_puts(out, "Signature Verification Failure\n");
336480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (rv == 1)
337480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_puts(out, "Signature Verified Successfully\n");
338480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rv >= 0)
339480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			goto end;
340480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
341480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
342480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
343480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
344480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			      buf_in, (size_t)buf_inlen);
345480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (rv > 0)
346480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
347480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			buf_out = OPENSSL_malloc(buf_outlen);
348480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!buf_out)
349480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				rv = -1;
350480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			else
351480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				rv = do_keyop(ctx, pkey_op,
352480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						buf_out, (size_t *)&buf_outlen,
353480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org						buf_in, (size_t)buf_inlen);
354480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
355480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
356480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
357480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(rv <= 0)
358480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
359480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_printf(bio_err, "Public Key operation error\n");
360480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ERR_print_errors(bio_err);
361480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
362480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
363480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = 0;
364480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(asn1parse)
365480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
366480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
367480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			ERR_print_errors(bio_err);
368480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
369480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else if(hexdump)
370480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_dump(out, (char *)buf_out, buf_outlen);
371480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
372480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_write(out, buf_out, buf_outlen);
373480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
374480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	end:
375480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ctx)
376480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_CTX_free(ctx);
377480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_free(in);
378480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_free_all(out);
379480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (buf_in)
380480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(buf_in);
381480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (buf_out)
382480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(buf_out);
383480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (sig)
384480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(sig);
385480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return ret;
386480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org}
387480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
388480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic void usage()
389480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org{
390480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
391480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-in file        input file\n");
392480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-out file       output file\n");
393480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
394480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-inkey file     input key\n");
395480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
396480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-pubin          input is a public key\n");
397480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-certin         input is a certificate carrying a public key\n");
398480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-pkeyopt X:Y    public key options\n");
399480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-sign           sign with private key\n");
400480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-verify         verify with public key\n");
401480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-verifyrecover  verify with public key, recover original data\n");
402480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
403480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
404480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-derive         derive shared secret\n");
405480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-hexdump        hex dump output\n");
406480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#ifndef OPENSSL_NO_ENGINE
407480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
408480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
409480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	BIO_printf(bio_err, "-passin arg     pass phrase source\n");
410480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
411480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org}
412480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
413480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic EVP_PKEY_CTX *init_ctx(int *pkeysize,
414480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				char *keyfile, int keyform, int key_type,
415480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				char *passargin, int pkey_op, ENGINE *e)
416480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
417480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY *pkey = NULL;
418480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_CTX *ctx = NULL;
419480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	char *passin = NULL;
420480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int rv = -1;
421480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509 *x;
422480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
423480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		|| (pkey_op == EVP_PKEY_OP_DERIVE))
424480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		&& (key_type != KEY_PRIVKEY))
425480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
426480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_printf(bio_err, "A private key is needed for this operation\n");
427480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
428480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
429480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
430480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
431480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_printf(bio_err, "Error getting password\n");
432480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
433480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
434480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	switch(key_type)
435480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
436480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case KEY_PRIVKEY:
437480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		pkey = load_key(bio_err, keyfile, keyform, 0,
438480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			passin, e, "Private Key");
439480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
440480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
441480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case KEY_PUBKEY:
442480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		pkey = load_pubkey(bio_err, keyfile, keyform, 0,
443480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			NULL, e, "Public Key");
444480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
445480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
446480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case KEY_CERT:
447480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		x = load_cert(bio_err, keyfile, keyform,
448480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			NULL, e, "Certificate");
449480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(x)
450480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
451480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			pkey = X509_get_pubkey(x);
452480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_free(x);
453480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
454480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
455480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
456480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
457480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
458480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	*pkeysize = EVP_PKEY_size(pkey);
459480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
460480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!pkey)
461480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
462480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
463480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ctx = EVP_PKEY_CTX_new(pkey, e);
464480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
465480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_free(pkey);
466480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
467480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!ctx)
468480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		goto end;
469480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
470480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	switch(pkey_op)
471480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
472480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_SIGN:
473480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = EVP_PKEY_sign_init(ctx);
474480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
475480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
476480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_VERIFY:
477480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = EVP_PKEY_verify_init(ctx);
478480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
479480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
480480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_VERIFYRECOVER:
481480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = EVP_PKEY_verify_recover_init(ctx);
482480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
483480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
484480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_ENCRYPT:
485480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = EVP_PKEY_encrypt_init(ctx);
486480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
487480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
488480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_DECRYPT:
489480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = EVP_PKEY_decrypt_init(ctx);
490480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
491480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
492480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_DERIVE:
493480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv = EVP_PKEY_derive_init(ctx);
494480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
495480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
496480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
497480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (rv <= 0)
498480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
499480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_CTX_free(ctx);
500480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ctx = NULL;
501480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
502480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
503480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	end:
504480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
505480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (passin)
506480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		OPENSSL_free(passin);
507480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
508480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return ctx;
509480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
510480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
511480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
512480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
513480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
514480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org							const char *file)
515480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
516480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY *peer = NULL;
517480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int ret;
518480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!ctx)
519480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
520480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_puts(err, "-peerkey command before -inkey\n");
521480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
522480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
523480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
524480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
525480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
526480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!peer)
527480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
528480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		BIO_printf(bio_err, "Error reading peer key %s\n", file);
529480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ERR_print_errors(err);
530480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
531480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
532480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
533480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ret = EVP_PKEY_derive_set_peer(ctx, peer);
534480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
535480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	EVP_PKEY_free(peer);
536480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ret <= 0)
537480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ERR_print_errors(err);
538480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return ret;
539480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
540480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
541480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.orgstatic int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
542480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		unsigned char *out, size_t *poutlen,
543480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		unsigned char *in, size_t inlen)
544480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	{
545480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	int rv = 0;
546480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	switch(pkey_op)
547480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
548480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_VERIFYRECOVER:
549480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv  = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
550480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
551480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
552480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_SIGN:
553480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv  = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
554480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
555480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
556480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_ENCRYPT:
557480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv  = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
558480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
559480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
560480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_DECRYPT:
561480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv  = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
562480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
563480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
564480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		case EVP_PKEY_OP_DERIVE:
565480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		rv  = EVP_PKEY_derive(ctx, out, poutlen);
566480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
567480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
568480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
569480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	return rv;
570480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	}
571