dgst.c revision 279264
164562Sgshapiro/* apps/dgst.c */
264562Sgshapiro/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
364562Sgshapiro * All rights reserved.
464562Sgshapiro *
564562Sgshapiro * This package is an SSL implementation written
6111823Sgshapiro * by Eric Young (eay@cryptsoft.com).
764562Sgshapiro * The implementation was written so as to conform with Netscapes SSL.
864562Sgshapiro *
964562Sgshapiro * This library is free for commercial and non-commercial use as long as
1064562Sgshapiro * the following conditions are aheared to.  The following conditions
1164562Sgshapiro * apply to all code found in this distribution, be it the RC4, RSA,
1264562Sgshapiro * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1364562Sgshapiro * included with this distribution is covered by the same copyright terms
1464562Sgshapiro * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1564562Sgshapiro *
1664562Sgshapiro * Copyright remains Eric Young's, and as such any Copyright notices in
17159609Sgshapiro * the code are not to be removed.
1864562Sgshapiro * If this package is used in a product, Eric Young should be given attribution
1964562Sgshapiro * as the author of the parts of the library used.
2064562Sgshapiro * This can be in the form of a textual message at program startup or
2164562Sgshapiro * in documentation (online or textual) provided with the package.
2264562Sgshapiro *
2364562Sgshapiro * Redistribution and use in source and binary forms, with or without
2464562Sgshapiro * modification, are permitted provided that the following conditions
2564562Sgshapiro * are met:
26159609Sgshapiro * 1. Redistributions of source code must retain the copyright
27159609Sgshapiro *    notice, this list of conditions and the following disclaimer.
28159609Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright
29159609Sgshapiro *    notice, this list of conditions and the following disclaimer in the
30159609Sgshapiro *    documentation and/or other materials provided with the distribution.
31159609Sgshapiro * 3. All advertising materials mentioning features or use of this software
32159609Sgshapiro *    must display the following acknowledgement:
33159609Sgshapiro *    "This product includes cryptographic software written by
34159609Sgshapiro *     Eric Young (eay@cryptsoft.com)"
35159609Sgshapiro *    The word 'cryptographic' can be left out if the rouines from the library
36159609Sgshapiro *    being used are not cryptographic related :-).
37159609Sgshapiro * 4. If you include any Windows specific code (or a derivative thereof) from
38159609Sgshapiro *    the apps directory (application code) you must include an acknowledgement:
39159609Sgshapiro *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40159609Sgshapiro *
41159609Sgshapiro * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42159609Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43159609Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44159609Sgshapiro * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45159609Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46159609Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4780785Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48159609Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49159609Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50159609Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51159609Sgshapiro * SUCH DAMAGE.
52159609Sgshapiro *
53159609Sgshapiro * The licence and distribution terms for any publically available version or
54159609Sgshapiro * derivative of this code cannot be changed.  i.e. this code cannot simply be
55159609Sgshapiro * copied and put under another distribution licence
56159609Sgshapiro * [including the GNU Public Licence.]
57159609Sgshapiro */
58159609Sgshapiro
59159609Sgshapiro#include <stdio.h>
60159609Sgshapiro#include <string.h>
61159609Sgshapiro#include <stdlib.h>
62159609Sgshapiro#include "apps.h"
63159609Sgshapiro#include <openssl/bio.h>
64159609Sgshapiro#include <openssl/err.h>
65159609Sgshapiro#include <openssl/evp.h>
6680785Sgshapiro#include <openssl/objects.h>
67159609Sgshapiro#include <openssl/x509.h>
68159609Sgshapiro#include <openssl/pem.h>
69159609Sgshapiro#include <openssl/hmac.h>
70159609Sgshapiro
71159609Sgshapiro#undef BUFSIZE
72159609Sgshapiro#define BUFSIZE	1024*8
73159609Sgshapiro
74159609Sgshapiro#undef PROG
75159609Sgshapiro#define PROG	dgst_main
76159609Sgshapiro
77159609Sgshapiroint do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
78159609Sgshapiro	  EVP_PKEY *key, unsigned char *sigin, int siglen,
79159609Sgshapiro	  const char *sig_name, const char *md_name,
80159609Sgshapiro	  const char *file,BIO *bmd);
81159609Sgshapiro
82159609Sgshapirostatic void list_md_fn(const EVP_MD *m,
83159609Sgshapiro			const char *from, const char *to, void *arg)
84159609Sgshapiro	{
85159609Sgshapiro	const char *mname;
86159609Sgshapiro	/* Skip aliases */
87159609Sgshapiro	if (!m)
88159609Sgshapiro		return;
89159609Sgshapiro	mname = OBJ_nid2ln(EVP_MD_type(m));
90159609Sgshapiro	/* Skip shortnames */
91159609Sgshapiro	if (strcmp(from, mname))
92159609Sgshapiro		return;
93159609Sgshapiro	/* Skip clones */
94159609Sgshapiro	if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST)
95159609Sgshapiro		return;
96159609Sgshapiro	if (strchr(mname, ' '))
97159609Sgshapiro		mname= EVP_MD_name(m);
98159609Sgshapiro	BIO_printf(arg, "-%-14s to use the %s message digest algorithm\n",
99159609Sgshapiro			mname, mname);
100159609Sgshapiro	}
101159609Sgshapiro
102159609Sgshapiroint MAIN(int, char **);
103159609Sgshapiro
104159609Sgshapiroint MAIN(int argc, char **argv)
105159609Sgshapiro	{
106159609Sgshapiro	ENGINE *e = NULL;
107159609Sgshapiro	unsigned char *buf=NULL;
108159609Sgshapiro	int i,err=1;
109159609Sgshapiro	const EVP_MD *md=NULL,*m;
110159609Sgshapiro	BIO *in=NULL,*inp;
111159609Sgshapiro	BIO *bmd=NULL;
112159609Sgshapiro	BIO *out = NULL;
113159609Sgshapiro#define PROG_NAME_SIZE  39
114159609Sgshapiro	char pname[PROG_NAME_SIZE+1];
115159609Sgshapiro	int separator=0;
116159609Sgshapiro	int debug=0;
117159609Sgshapiro	int keyform=FORMAT_PEM;
118159609Sgshapiro	const char *outfile = NULL, *keyfile = NULL;
119159609Sgshapiro	const char *sigfile = NULL, *randfile = NULL;
120159609Sgshapiro	int out_bin = -1, want_pub = 0, do_verify = 0;
121159609Sgshapiro	EVP_PKEY *sigkey = NULL;
122159609Sgshapiro	unsigned char *sigbuf = NULL;
123159609Sgshapiro	int siglen = 0;
124159609Sgshapiro	char *passargin = NULL, *passin = NULL;
125159609Sgshapiro#ifndef OPENSSL_NO_ENGINE
126159609Sgshapiro	char *engine=NULL;
127159609Sgshapiro#endif
128159609Sgshapiro	char *hmac_key=NULL;
129159609Sgshapiro	char *mac_name=NULL;
130159609Sgshapiro	int non_fips_allow = 0;
131159609Sgshapiro	STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
132159609Sgshapiro
133159609Sgshapiro	apps_startup();
134159609Sgshapiro
135159609Sgshapiro	if ((buf=(unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL)
136159609Sgshapiro		{
137159609Sgshapiro		BIO_printf(bio_err,"out of memory\n");
138159609Sgshapiro		goto end;
139159609Sgshapiro		}
140159609Sgshapiro	if (bio_err == NULL)
141159609Sgshapiro		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
14264562Sgshapiro			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
14364562Sgshapiro
14464562Sgshapiro	if (!load_config(bio_err, NULL))
145261370Sgshapiro		goto end;
146261370Sgshapiro
147261370Sgshapiro	/* first check the program name */
148261370Sgshapiro	program_name(argv[0],pname,sizeof pname);
149261370Sgshapiro
150261370Sgshapiro	md=EVP_get_digestbyname(pname);
151261370Sgshapiro
152261370Sgshapiro	argc--;
153261370Sgshapiro	argv++;
154261370Sgshapiro	while (argc > 0)
155261370Sgshapiro		{
156261370Sgshapiro		if ((*argv)[0] != '-') break;
157261370Sgshapiro		if (strcmp(*argv,"-c") == 0)
158261370Sgshapiro			separator=1;
159261370Sgshapiro		else if (strcmp(*argv,"-r") == 0)
160261370Sgshapiro			separator=2;
161261370Sgshapiro		else if (strcmp(*argv,"-rand") == 0)
162261370Sgshapiro			{
163261370Sgshapiro			if (--argc < 1) break;
164261370Sgshapiro			randfile=*(++argv);
165261370Sgshapiro			}
166261370Sgshapiro		else if (strcmp(*argv,"-out") == 0)
167261370Sgshapiro			{
168261370Sgshapiro			if (--argc < 1) break;
169261370Sgshapiro			outfile=*(++argv);
170261370Sgshapiro			}
171261370Sgshapiro		else if (strcmp(*argv,"-sign") == 0)
172261370Sgshapiro			{
173261370Sgshapiro			if (--argc < 1) break;
174261370Sgshapiro			keyfile=*(++argv);
175261370Sgshapiro			}
176261370Sgshapiro		else if (!strcmp(*argv,"-passin"))
177261370Sgshapiro			{
178261370Sgshapiro			if (--argc < 1)
179261370Sgshapiro				break;
180261370Sgshapiro			passargin=*++argv;
181261370Sgshapiro			}
182261370Sgshapiro		else if (strcmp(*argv,"-verify") == 0)
183261370Sgshapiro			{
184261370Sgshapiro			if (--argc < 1) break;
185261370Sgshapiro			keyfile=*(++argv);
186261370Sgshapiro			want_pub = 1;
187261370Sgshapiro			do_verify = 1;
188261370Sgshapiro			}
189261370Sgshapiro		else if (strcmp(*argv,"-prverify") == 0)
190261370Sgshapiro			{
191261370Sgshapiro			if (--argc < 1) break;
192261370Sgshapiro			keyfile=*(++argv);
193261370Sgshapiro			do_verify = 1;
194261370Sgshapiro			}
195261370Sgshapiro		else if (strcmp(*argv,"-signature") == 0)
196261370Sgshapiro			{
197261370Sgshapiro			if (--argc < 1) break;
198261370Sgshapiro			sigfile=*(++argv);
199261370Sgshapiro			}
200261370Sgshapiro		else if (strcmp(*argv,"-keyform") == 0)
201261370Sgshapiro			{
202261370Sgshapiro			if (--argc < 1) break;
203261370Sgshapiro			keyform=str2fmt(*(++argv));
204261370Sgshapiro			}
205261370Sgshapiro#ifndef OPENSSL_NO_ENGINE
206261370Sgshapiro		else if (strcmp(*argv,"-engine") == 0)
207261370Sgshapiro			{
208261370Sgshapiro			if (--argc < 1) break;
209261370Sgshapiro			engine= *(++argv);
210261370Sgshapiro        		e = setup_engine(bio_err, engine, 0);
211261370Sgshapiro			}
212261370Sgshapiro#endif
213261370Sgshapiro		else if (strcmp(*argv,"-hex") == 0)
214261370Sgshapiro			out_bin = 0;
215261370Sgshapiro		else if (strcmp(*argv,"-binary") == 0)
216261370Sgshapiro			out_bin = 1;
217261370Sgshapiro		else if (strcmp(*argv,"-d") == 0)
218261370Sgshapiro			debug=1;
219261370Sgshapiro		else if (!strcmp(*argv,"-fips-fingerprint"))
220261370Sgshapiro			hmac_key = "etaonrishdlcupfm";
221261370Sgshapiro		else if (strcmp(*argv,"-non-fips-allow") == 0)
222261370Sgshapiro			non_fips_allow=1;
223261370Sgshapiro		else if (!strcmp(*argv,"-hmac"))
224261370Sgshapiro			{
225261370Sgshapiro			if (--argc < 1)
226261370Sgshapiro				break;
227261370Sgshapiro			hmac_key=*++argv;
228261370Sgshapiro			}
229261370Sgshapiro		else if (!strcmp(*argv,"-mac"))
230261370Sgshapiro			{
231261370Sgshapiro			if (--argc < 1)
232261370Sgshapiro				break;
233261370Sgshapiro			mac_name=*++argv;
234261370Sgshapiro			}
235261370Sgshapiro		else if (strcmp(*argv,"-sigopt") == 0)
236261370Sgshapiro			{
237261370Sgshapiro			if (--argc < 1)
238261370Sgshapiro				break;
239261370Sgshapiro			if (!sigopts)
240261370Sgshapiro				sigopts = sk_OPENSSL_STRING_new_null();
241261370Sgshapiro			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
242261370Sgshapiro				break;
243261370Sgshapiro			}
244261370Sgshapiro		else if (strcmp(*argv,"-macopt") == 0)
245261370Sgshapiro			{
246261370Sgshapiro			if (--argc < 1)
247261370Sgshapiro				break;
248261370Sgshapiro			if (!macopts)
249261370Sgshapiro				macopts = sk_OPENSSL_STRING_new_null();
250261370Sgshapiro			if (!macopts || !sk_OPENSSL_STRING_push(macopts, *(++argv)))
251261370Sgshapiro				break;
252261370Sgshapiro			}
253261370Sgshapiro		else if ((m=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
254261370Sgshapiro			md=m;
255261370Sgshapiro		else
256261370Sgshapiro			break;
257261370Sgshapiro		argc--;
258261370Sgshapiro		argv++;
259261370Sgshapiro		}
260261370Sgshapiro
261261370Sgshapiro
262261370Sgshapiro	if(do_verify && !sigfile) {
263261370Sgshapiro		BIO_printf(bio_err, "No signature to verify: use the -signature option\n");
264261370Sgshapiro		goto end;
265261370Sgshapiro	}
266261370Sgshapiro
267261370Sgshapiro	if ((argc > 0) && (argv[0][0] == '-')) /* bad option */
268261370Sgshapiro		{
269261370Sgshapiro		BIO_printf(bio_err,"unknown option '%s'\n",*argv);
270261370Sgshapiro		BIO_printf(bio_err,"options are\n");
271261370Sgshapiro		BIO_printf(bio_err,"-c              to output the digest with separating colons\n");
272261370Sgshapiro		BIO_printf(bio_err,"-r              to output the digest in coreutils format\n");
273261370Sgshapiro		BIO_printf(bio_err,"-d              to output debug info\n");
274261370Sgshapiro		BIO_printf(bio_err,"-hex            output as hex dump\n");
275261370Sgshapiro		BIO_printf(bio_err,"-binary         output in binary form\n");
276261370Sgshapiro		BIO_printf(bio_err,"-hmac arg       set the HMAC key to arg\n");
277261370Sgshapiro		BIO_printf(bio_err,"-non-fips-allow allow use of non FIPS digest\n");
278261370Sgshapiro		BIO_printf(bio_err,"-sign   file    sign digest using private key in file\n");
279261370Sgshapiro		BIO_printf(bio_err,"-verify file    verify a signature using public key in file\n");
280261370Sgshapiro		BIO_printf(bio_err,"-prverify file  verify a signature using private key in file\n");
281261370Sgshapiro		BIO_printf(bio_err,"-keyform arg    key file format (PEM or ENGINE)\n");
282261370Sgshapiro		BIO_printf(bio_err,"-out filename   output to filename rather than stdout\n");
283261370Sgshapiro		BIO_printf(bio_err,"-signature file signature to verify\n");
284261370Sgshapiro		BIO_printf(bio_err,"-sigopt nm:v    signature parameter\n");
285261370Sgshapiro		BIO_printf(bio_err,"-hmac key       create hashed MAC with key\n");
286261370Sgshapiro		BIO_printf(bio_err,"-mac algorithm  create MAC (not neccessarily HMAC)\n");
287261370Sgshapiro		BIO_printf(bio_err,"-macopt nm:v    MAC algorithm parameters or key\n");
288261370Sgshapiro#ifndef OPENSSL_NO_ENGINE
289261370Sgshapiro		BIO_printf(bio_err,"-engine e       use engine e, possibly a hardware device.\n");
290261370Sgshapiro#endif
291261370Sgshapiro
292261370Sgshapiro		EVP_MD_do_all_sorted(list_md_fn, bio_err);
293261370Sgshapiro		goto end;
294261370Sgshapiro		}
295261370Sgshapiro
296261370Sgshapiro	in=BIO_new(BIO_s_file());
297261370Sgshapiro	bmd=BIO_new(BIO_f_md());
298261370Sgshapiro	if (debug)
299261370Sgshapiro		{
300261370Sgshapiro		BIO_set_callback(in,BIO_debug_callback);
301261370Sgshapiro		/* needed for windows 3.1 */
302261370Sgshapiro		BIO_set_callback_arg(in,(char *)bio_err);
303261370Sgshapiro		}
304261370Sgshapiro
305261370Sgshapiro	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
306261370Sgshapiro		{
307261370Sgshapiro		BIO_printf(bio_err, "Error getting password\n");
308261370Sgshapiro		goto end;
309261370Sgshapiro		}
310261370Sgshapiro
311261370Sgshapiro	if ((in == NULL) || (bmd == NULL))
312261370Sgshapiro		{
313261370Sgshapiro		ERR_print_errors(bio_err);
314261370Sgshapiro		goto end;
315261370Sgshapiro		}
316261370Sgshapiro
317261370Sgshapiro	if(out_bin == -1) {
318261370Sgshapiro		if(keyfile)
319261370Sgshapiro			out_bin = 1;
320261370Sgshapiro		else
321261370Sgshapiro			out_bin = 0;
322261370Sgshapiro	}
323249865Sgshapiro
324249865Sgshapiro	if(randfile)
325249865Sgshapiro		app_RAND_load_file(randfile, bio_err, 0);
326249865Sgshapiro
327249865Sgshapiro	if(outfile) {
328249865Sgshapiro		if(out_bin)
329249865Sgshapiro			out = BIO_new_file(outfile, "wb");
330249865Sgshapiro		else    out = BIO_new_file(outfile, "w");
331249865Sgshapiro	} else {
332249865Sgshapiro		out = BIO_new_fp(stdout, BIO_NOCLOSE);
333249865Sgshapiro#ifdef OPENSSL_SYS_VMS
334249865Sgshapiro		{
335249865Sgshapiro		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
336249865Sgshapiro		out = BIO_push(tmpbio, out);
337249865Sgshapiro		}
338249865Sgshapiro#endif
339249865Sgshapiro	}
340249865Sgshapiro
341249865Sgshapiro	if(!out) {
342249865Sgshapiro		BIO_printf(bio_err, "Error opening output file %s\n",
343249865Sgshapiro					outfile ? outfile : "(stdout)");
344249865Sgshapiro		ERR_print_errors(bio_err);
345249865Sgshapiro		goto end;
346249865Sgshapiro	}
347249865Sgshapiro	if ((!!mac_name + !!keyfile + !!hmac_key) > 1)
348249865Sgshapiro		{
349249865Sgshapiro		BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
350249865Sgshapiro		goto end;
351249865Sgshapiro		}
352249865Sgshapiro
353249865Sgshapiro	if(keyfile)
354249865Sgshapiro		{
355249865Sgshapiro		if (want_pub)
356249865Sgshapiro			sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL,
357249865Sgshapiro				e, "key file");
358249865Sgshapiro		else
359249865Sgshapiro			sigkey = load_key(bio_err, keyfile, keyform, 0, passin,
360249865Sgshapiro				e, "key file");
361249865Sgshapiro		if (!sigkey)
362249865Sgshapiro			{
363249865Sgshapiro			/* load_[pub]key() has already printed an appropriate
364249865Sgshapiro			   message */
365249865Sgshapiro			goto end;
366249865Sgshapiro			}
367249865Sgshapiro		}
368249865Sgshapiro
369249865Sgshapiro	if (mac_name)
370249865Sgshapiro		{
371249865Sgshapiro		EVP_PKEY_CTX *mac_ctx = NULL;
372249865Sgshapiro		int r = 0;
373249865Sgshapiro		if (!init_gen_str(bio_err, &mac_ctx, mac_name,e, 0))
374249865Sgshapiro			goto mac_end;
375249865Sgshapiro		if (macopts)
376249865Sgshapiro			{
377249865Sgshapiro			char *macopt;
378249865Sgshapiro			for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++)
379249865Sgshapiro				{
380249865Sgshapiro				macopt = sk_OPENSSL_STRING_value(macopts, i);
381249865Sgshapiro				if (pkey_ctrl_string(mac_ctx, macopt) <= 0)
382249865Sgshapiro					{
383249865Sgshapiro					BIO_printf(bio_err,
384249865Sgshapiro						"MAC parameter error \"%s\"\n",
385249865Sgshapiro						macopt);
386249865Sgshapiro					ERR_print_errors(bio_err);
387249865Sgshapiro					goto mac_end;
388249865Sgshapiro					}
389249865Sgshapiro				}
390249865Sgshapiro			}
391249865Sgshapiro		if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0)
392249865Sgshapiro			{
393249865Sgshapiro			BIO_puts(bio_err, "Error generating key\n");
394249865Sgshapiro			ERR_print_errors(bio_err);
395249865Sgshapiro			goto mac_end;
396249865Sgshapiro			}
397249865Sgshapiro		r = 1;
398249865Sgshapiro		mac_end:
399249865Sgshapiro		if (mac_ctx)
400249865Sgshapiro			EVP_PKEY_CTX_free(mac_ctx);
401249865Sgshapiro		if (r == 0)
402249865Sgshapiro			goto end;
403249865Sgshapiro		}
404249865Sgshapiro
405249865Sgshapiro	if (non_fips_allow)
406249865Sgshapiro		{
407249865Sgshapiro		EVP_MD_CTX *md_ctx;
408249865Sgshapiro		BIO_get_md_ctx(bmd,&md_ctx);
409249865Sgshapiro		EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
410249865Sgshapiro		}
411249865Sgshapiro
412249865Sgshapiro	if (hmac_key)
413249865Sgshapiro		{
414249865Sgshapiro		sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
415249865Sgshapiro					(unsigned char *)hmac_key, -1);
416249865Sgshapiro		if (!sigkey)
417249865Sgshapiro			goto end;
418249865Sgshapiro		}
419249865Sgshapiro
420249865Sgshapiro	if (sigkey)
421249865Sgshapiro		{
422249865Sgshapiro		EVP_MD_CTX *mctx = NULL;
423249865Sgshapiro		EVP_PKEY_CTX *pctx = NULL;
424249865Sgshapiro		int r;
425249865Sgshapiro		if (!BIO_get_md_ctx(bmd, &mctx))
426249865Sgshapiro			{
427249865Sgshapiro			BIO_printf(bio_err, "Error getting context\n");
428249865Sgshapiro			ERR_print_errors(bio_err);
429249865Sgshapiro			goto end;
430249865Sgshapiro			}
431249865Sgshapiro		if (do_verify)
432249865Sgshapiro			r = EVP_DigestVerifyInit(mctx, &pctx, md, NULL, sigkey);
433249865Sgshapiro		else
434249865Sgshapiro			r = EVP_DigestSignInit(mctx, &pctx, md, NULL, sigkey);
435249865Sgshapiro		if (!r)
436249865Sgshapiro			{
437249865Sgshapiro			BIO_printf(bio_err, "Error setting context\n");
438249865Sgshapiro			ERR_print_errors(bio_err);
439249865Sgshapiro			goto end;
440249865Sgshapiro			}
441249865Sgshapiro		if (sigopts)
442249865Sgshapiro			{
443249865Sgshapiro			char *sigopt;
444249865Sgshapiro			for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++)
445249865Sgshapiro				{
446249865Sgshapiro				sigopt = sk_OPENSSL_STRING_value(sigopts, i);
447249865Sgshapiro				if (pkey_ctrl_string(pctx, sigopt) <= 0)
448249865Sgshapiro					{
449249865Sgshapiro					BIO_printf(bio_err,
450249865Sgshapiro						"parameter error \"%s\"\n",
451249865Sgshapiro						sigopt);
452249865Sgshapiro					ERR_print_errors(bio_err);
453249865Sgshapiro					goto end;
454249865Sgshapiro					}
455249865Sgshapiro				}
456249865Sgshapiro			}
457249865Sgshapiro		}
458249865Sgshapiro	/* we use md as a filter, reading from 'in' */
459249865Sgshapiro	else
460244928Sgshapiro		{
461244928Sgshapiro		if (md == NULL)
462244928Sgshapiro			md = EVP_md5();
463244928Sgshapiro		if (!BIO_set_md(bmd,md))
464244928Sgshapiro			{
465244928Sgshapiro			BIO_printf(bio_err, "Error setting digest %s\n", pname);
466244928Sgshapiro			ERR_print_errors(bio_err);
467244928Sgshapiro			goto end;
468244928Sgshapiro			}
469244928Sgshapiro		}
470244928Sgshapiro
471244928Sgshapiro	if(sigfile && sigkey) {
472244928Sgshapiro		BIO *sigbio;
473244928Sgshapiro		sigbio = BIO_new_file(sigfile, "rb");
474244928Sgshapiro		siglen = EVP_PKEY_size(sigkey);
475244928Sgshapiro		sigbuf = OPENSSL_malloc(siglen);
476244928Sgshapiro		if(!sigbio) {
477244928Sgshapiro			BIO_printf(bio_err, "Error opening signature file %s\n",
478244928Sgshapiro								sigfile);
479244928Sgshapiro			ERR_print_errors(bio_err);
480244928Sgshapiro			goto end;
481244928Sgshapiro		}
482244928Sgshapiro		siglen = BIO_read(sigbio, sigbuf, siglen);
483244928Sgshapiro		BIO_free(sigbio);
484244928Sgshapiro		if(siglen <= 0) {
485244928Sgshapiro			BIO_printf(bio_err, "Error reading signature file %s\n",
486244928Sgshapiro								sigfile);
487244928Sgshapiro			ERR_print_errors(bio_err);
488244928Sgshapiro			goto end;
489244928Sgshapiro		}
490244928Sgshapiro	}
491244928Sgshapiro	inp=BIO_push(bmd,in);
492244928Sgshapiro
493244928Sgshapiro	if (md == NULL)
494244928Sgshapiro		{
495244928Sgshapiro		EVP_MD_CTX *tctx;
496244928Sgshapiro		BIO_get_md_ctx(bmd, &tctx);
497244928Sgshapiro		md = EVP_MD_CTX_md(tctx);
498244928Sgshapiro		}
499244928Sgshapiro
500244928Sgshapiro	if (argc == 0)
501244928Sgshapiro		{
502244928Sgshapiro		BIO_set_fp(in,stdin,BIO_NOCLOSE);
503244928Sgshapiro		err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf,
504244928Sgshapiro			  siglen,NULL,NULL,"stdin",bmd);
505244928Sgshapiro		}
506244928Sgshapiro	else
507244928Sgshapiro		{
508244928Sgshapiro		const char *md_name = NULL, *sig_name = NULL;
509244928Sgshapiro		if(!out_bin)
510244928Sgshapiro			{
511244928Sgshapiro			if (sigkey)
512244928Sgshapiro				{
513244928Sgshapiro				const EVP_PKEY_ASN1_METHOD *ameth;
514244928Sgshapiro				ameth = EVP_PKEY_get0_asn1(sigkey);
515244928Sgshapiro				if (ameth)
516244928Sgshapiro					EVP_PKEY_asn1_get0_info(NULL, NULL,
517244928Sgshapiro						NULL, NULL, &sig_name, ameth);
518244928Sgshapiro				}
519244928Sgshapiro			md_name = EVP_MD_name(md);
520244928Sgshapiro			}
521244928Sgshapiro		err = 0;
522244928Sgshapiro		for (i=0; i<argc; i++)
523244928Sgshapiro			{
524244928Sgshapiro			int r;
525244928Sgshapiro			if (BIO_read_filename(in,argv[i]) <= 0)
526244928Sgshapiro				{
527244928Sgshapiro				perror(argv[i]);
528244928Sgshapiro				err++;
529244928Sgshapiro				continue;
530244928Sgshapiro				}
531244928Sgshapiro			else
532244928Sgshapiro			r=do_fp(out,buf,inp,separator,out_bin,sigkey,sigbuf,
533244928Sgshapiro				siglen,sig_name,md_name, argv[i],bmd);
534244928Sgshapiro			if(r)
535244928Sgshapiro			    err=r;
536244928Sgshapiro			(void)BIO_reset(bmd);
537244928Sgshapiro			}
538244928Sgshapiro		}
539244928Sgshapiroend:
540244928Sgshapiro	if (buf != NULL)
541244928Sgshapiro		{
542244928Sgshapiro		OPENSSL_cleanse(buf,BUFSIZE);
543244928Sgshapiro		OPENSSL_free(buf);
544244928Sgshapiro		}
545244928Sgshapiro	if (in != NULL) BIO_free(in);
546244928Sgshapiro	if (passin)
547244928Sgshapiro		OPENSSL_free(passin);
548244928Sgshapiro	BIO_free_all(out);
549244928Sgshapiro	EVP_PKEY_free(sigkey);
550244928Sgshapiro	if (sigopts)
551244928Sgshapiro		sk_OPENSSL_STRING_free(sigopts);
552244928Sgshapiro	if (macopts)
553244928Sgshapiro		sk_OPENSSL_STRING_free(macopts);
554244928Sgshapiro	if(sigbuf) OPENSSL_free(sigbuf);
555244928Sgshapiro	if (bmd != NULL) BIO_free(bmd);
556244928Sgshapiro	apps_shutdown();
557244928Sgshapiro	OPENSSL_EXIT(err);
558244928Sgshapiro	}
559244928Sgshapiro
560244928Sgshapiroint do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
561244928Sgshapiro	  EVP_PKEY *key, unsigned char *sigin, int siglen,
562244928Sgshapiro	  const char *sig_name, const char *md_name,
563244928Sgshapiro	  const char *file,BIO *bmd)
564244928Sgshapiro	{
565244928Sgshapiro	size_t len;
566244928Sgshapiro	int i;
567244928Sgshapiro
568244928Sgshapiro	for (;;)
569244928Sgshapiro		{
570244928Sgshapiro		i=BIO_read(bp,(char *)buf,BUFSIZE);
571244928Sgshapiro		if(i < 0)
572244928Sgshapiro			{
573244928Sgshapiro			BIO_printf(bio_err, "Read Error in %s\n",file);
574244928Sgshapiro			ERR_print_errors(bio_err);
575244928Sgshapiro			return 1;
576244928Sgshapiro			}
577244928Sgshapiro		if (i == 0) break;
578244928Sgshapiro		}
579244928Sgshapiro	if(sigin)
580244928Sgshapiro		{
581244928Sgshapiro		EVP_MD_CTX *ctx;
582244928Sgshapiro		BIO_get_md_ctx(bp, &ctx);
583244928Sgshapiro		i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
584244928Sgshapiro		if(i > 0)
585244928Sgshapiro			BIO_printf(out, "Verified OK\n");
586244928Sgshapiro		else if(i == 0)
587244928Sgshapiro			{
588244928Sgshapiro			BIO_printf(out, "Verification Failure\n");
589244928Sgshapiro			return 1;
590244928Sgshapiro			}
591244928Sgshapiro		else
592244928Sgshapiro			{
593244928Sgshapiro			BIO_printf(bio_err, "Error Verifying Data\n");
594244928Sgshapiro			ERR_print_errors(bio_err);
595244928Sgshapiro			return 1;
596244928Sgshapiro			}
597244928Sgshapiro		return 0;
598244928Sgshapiro		}
599244928Sgshapiro	if(key)
600244928Sgshapiro		{
601244928Sgshapiro		EVP_MD_CTX *ctx;
602244928Sgshapiro		BIO_get_md_ctx(bp, &ctx);
603223067Sgshapiro		len = BUFSIZE;
604223067Sgshapiro		if(!EVP_DigestSignFinal(ctx, buf, &len))
605223067Sgshapiro			{
606223067Sgshapiro			BIO_printf(bio_err, "Error Signing Data\n");
607223067Sgshapiro			ERR_print_errors(bio_err);
608223067Sgshapiro			return 1;
609223067Sgshapiro			}
610223067Sgshapiro		}
611223067Sgshapiro	else
612223067Sgshapiro		{
613223067Sgshapiro		len=BIO_gets(bp,(char *)buf,BUFSIZE);
614223067Sgshapiro		if ((int)len <0)
615223067Sgshapiro			{
616223067Sgshapiro			ERR_print_errors(bio_err);
617223067Sgshapiro			return 1;
618223067Sgshapiro			}
619223067Sgshapiro		}
620223067Sgshapiro
621223067Sgshapiro	if(binout) BIO_write(out, buf, len);
622223067Sgshapiro	else if (sep == 2)
623223067Sgshapiro		{
624223067Sgshapiro		for (i=0; i<(int)len; i++)
625223067Sgshapiro			BIO_printf(out, "%02x",buf[i]);
626223067Sgshapiro		BIO_printf(out, " *%s\n", file);
627223067Sgshapiro		}
628223067Sgshapiro	else
629223067Sgshapiro		{
630223067Sgshapiro		if (sig_name)
631223067Sgshapiro			BIO_printf(out, "%s-%s(%s)= ", sig_name, md_name, file);
632223067Sgshapiro		else if (md_name)
633223067Sgshapiro			BIO_printf(out, "%s(%s)= ", md_name, file);
634223067Sgshapiro		else
635223067Sgshapiro			BIO_printf(out, "(%s)= ", file);
636223067Sgshapiro		for (i=0; i<(int)len; i++)
637223067Sgshapiro			{
638223067Sgshapiro			if (sep && (i != 0))
639223067Sgshapiro				BIO_printf(out, ":");
640223067Sgshapiro			BIO_printf(out, "%02x",buf[i]);
641223067Sgshapiro			}
642223067Sgshapiro		BIO_printf(out, "\n");
643223067Sgshapiro		}
644223067Sgshapiro	return 0;
645223067Sgshapiro	}
646223067Sgshapiro
647223067Sgshapiro