155714Skris/* apps/dgst.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <string.h>
6155714Skris#include <stdlib.h>
6255714Skris#include "apps.h"
6355714Skris#include <openssl/bio.h>
6455714Skris#include <openssl/err.h>
6555714Skris#include <openssl/evp.h>
6655714Skris#include <openssl/objects.h>
6755714Skris#include <openssl/x509.h>
6855714Skris#include <openssl/pem.h>
69167612Ssimon#include <openssl/hmac.h>
7055714Skris
7155714Skris#undef BUFSIZE
7255714Skris#define BUFSIZE	1024*8
7355714Skris
7455714Skris#undef PROG
7555714Skris#define PROG	dgst_main
7655714Skris
77109998Smarkmint do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
78238405Sjkim	  EVP_PKEY *key, unsigned char *sigin, int siglen,
79238405Sjkim	  const char *sig_name, const char *md_name,
80238405Sjkim	  const char *file,BIO *bmd);
8159191Skris
82238405Sjkimstatic void list_md_fn(const EVP_MD *m,
83238405Sjkim			const char *from, const char *to, void *arg)
84238405Sjkim	{
85238405Sjkim	const char *mname;
86238405Sjkim	/* Skip aliases */
87238405Sjkim	if (!m)
88238405Sjkim		return;
89238405Sjkim	mname = OBJ_nid2ln(EVP_MD_type(m));
90238405Sjkim	/* Skip shortnames */
91238405Sjkim	if (strcmp(from, mname))
92238405Sjkim		return;
93238405Sjkim	/* Skip clones */
94238405Sjkim	if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST)
95238405Sjkim		return;
96238405Sjkim	if (strchr(mname, ' '))
97238405Sjkim		mname= EVP_MD_name(m);
98238405Sjkim	BIO_printf(arg, "-%-14s to use the %s message digest algorithm\n",
99238405Sjkim			mname, mname);
100238405Sjkim	}
101238405Sjkim
10259191Skrisint MAIN(int, char **);
10359191Skris
10455714Skrisint MAIN(int argc, char **argv)
10555714Skris	{
106109998Smarkm	ENGINE *e = NULL;
10755714Skris	unsigned char *buf=NULL;
108194206Ssimon	int i,err=1;
10955714Skris	const EVP_MD *md=NULL,*m;
11055714Skris	BIO *in=NULL,*inp;
11155714Skris	BIO *bmd=NULL;
11268651Skris	BIO *out = NULL;
113100928Snectar#define PROG_NAME_SIZE  39
114100928Snectar	char pname[PROG_NAME_SIZE+1];
11555714Skris	int separator=0;
11655714Skris	int debug=0;
117109998Smarkm	int keyform=FORMAT_PEM;
11868651Skris	const char *outfile = NULL, *keyfile = NULL;
11968651Skris	const char *sigfile = NULL, *randfile = NULL;
12079998Skris	int out_bin = -1, want_pub = 0, do_verify = 0;
12168651Skris	EVP_PKEY *sigkey = NULL;
12268651Skris	unsigned char *sigbuf = NULL;
12368651Skris	int siglen = 0;
124160814Ssimon	char *passargin = NULL, *passin = NULL;
125111147Snectar#ifndef OPENSSL_NO_ENGINE
126109998Smarkm	char *engine=NULL;
127111147Snectar#endif
128167612Ssimon	char *hmac_key=NULL;
129238405Sjkim	char *mac_name=NULL;
130194206Ssimon	int non_fips_allow = 0;
131238405Sjkim	STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
13255714Skris
13355714Skris	apps_startup();
134238405Sjkim
13568651Skris	if ((buf=(unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL)
13655714Skris		{
13755714Skris		BIO_printf(bio_err,"out of memory\n");
13855714Skris		goto end;
13955714Skris		}
14055714Skris	if (bio_err == NULL)
14155714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
14255714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
14355714Skris
144109998Smarkm	if (!load_config(bio_err, NULL))
145109998Smarkm		goto end;
146109998Smarkm
14755714Skris	/* first check the program name */
148109998Smarkm	program_name(argv[0],pname,sizeof pname);
14955714Skris
15055714Skris	md=EVP_get_digestbyname(pname);
15155714Skris
15255714Skris	argc--;
15355714Skris	argv++;
15455714Skris	while (argc > 0)
15555714Skris		{
15655714Skris		if ((*argv)[0] != '-') break;
15755714Skris		if (strcmp(*argv,"-c") == 0)
15855714Skris			separator=1;
159238405Sjkim		else if (strcmp(*argv,"-r") == 0)
160238405Sjkim			separator=2;
16168651Skris		else if (strcmp(*argv,"-rand") == 0)
16268651Skris			{
16368651Skris			if (--argc < 1) break;
16468651Skris			randfile=*(++argv);
16568651Skris			}
16668651Skris		else if (strcmp(*argv,"-out") == 0)
16768651Skris			{
16868651Skris			if (--argc < 1) break;
16968651Skris			outfile=*(++argv);
17068651Skris			}
17168651Skris		else if (strcmp(*argv,"-sign") == 0)
17268651Skris			{
17368651Skris			if (--argc < 1) break;
17468651Skris			keyfile=*(++argv);
17568651Skris			}
176160814Ssimon		else if (!strcmp(*argv,"-passin"))
177160814Ssimon			{
178160814Ssimon			if (--argc < 1)
179160814Ssimon				break;
180160814Ssimon			passargin=*++argv;
181160814Ssimon			}
18268651Skris		else if (strcmp(*argv,"-verify") == 0)
18368651Skris			{
18468651Skris			if (--argc < 1) break;
18568651Skris			keyfile=*(++argv);
18668651Skris			want_pub = 1;
18768651Skris			do_verify = 1;
18868651Skris			}
18968651Skris		else if (strcmp(*argv,"-prverify") == 0)
19068651Skris			{
19168651Skris			if (--argc < 1) break;
19268651Skris			keyfile=*(++argv);
19368651Skris			do_verify = 1;
19468651Skris			}
19568651Skris		else if (strcmp(*argv,"-signature") == 0)
19668651Skris			{
19768651Skris			if (--argc < 1) break;
19868651Skris			sigfile=*(++argv);
19968651Skris			}
200109998Smarkm		else if (strcmp(*argv,"-keyform") == 0)
201109998Smarkm			{
202109998Smarkm			if (--argc < 1) break;
203109998Smarkm			keyform=str2fmt(*(++argv));
204109998Smarkm			}
205111147Snectar#ifndef OPENSSL_NO_ENGINE
206109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
207109998Smarkm			{
208109998Smarkm			if (--argc < 1) break;
209109998Smarkm			engine= *(++argv);
210238405Sjkim        		e = setup_engine(bio_err, engine, 0);
211109998Smarkm			}
212111147Snectar#endif
21368651Skris		else if (strcmp(*argv,"-hex") == 0)
21468651Skris			out_bin = 0;
21568651Skris		else if (strcmp(*argv,"-binary") == 0)
21668651Skris			out_bin = 1;
21755714Skris		else if (strcmp(*argv,"-d") == 0)
21855714Skris			debug=1;
219246772Sjkim		else if (!strcmp(*argv,"-fips-fingerprint"))
220246772Sjkim			hmac_key = "etaonrishdlcupfm";
221194206Ssimon		else if (strcmp(*argv,"-non-fips-allow") == 0)
222194206Ssimon			non_fips_allow=1;
223167612Ssimon		else if (!strcmp(*argv,"-hmac"))
224167612Ssimon			{
225167612Ssimon			if (--argc < 1)
226167612Ssimon				break;
227167612Ssimon			hmac_key=*++argv;
228167612Ssimon			}
229238405Sjkim		else if (!strcmp(*argv,"-mac"))
230238405Sjkim			{
231238405Sjkim			if (--argc < 1)
232238405Sjkim				break;
233238405Sjkim			mac_name=*++argv;
234238405Sjkim			}
235238405Sjkim		else if (strcmp(*argv,"-sigopt") == 0)
236238405Sjkim			{
237238405Sjkim			if (--argc < 1)
238238405Sjkim				break;
239238405Sjkim			if (!sigopts)
240238405Sjkim				sigopts = sk_OPENSSL_STRING_new_null();
241238405Sjkim			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
242238405Sjkim				break;
243238405Sjkim			}
244238405Sjkim		else if (strcmp(*argv,"-macopt") == 0)
245238405Sjkim			{
246238405Sjkim			if (--argc < 1)
247238405Sjkim				break;
248238405Sjkim			if (!macopts)
249238405Sjkim				macopts = sk_OPENSSL_STRING_new_null();
250238405Sjkim			if (!macopts || !sk_OPENSSL_STRING_push(macopts, *(++argv)))
251238405Sjkim				break;
252238405Sjkim			}
25355714Skris		else if ((m=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
25455714Skris			md=m;
25555714Skris		else
25655714Skris			break;
25755714Skris		argc--;
25855714Skris		argv++;
25955714Skris		}
26055714Skris
26155714Skris
26268651Skris	if(do_verify && !sigfile) {
26368651Skris		BIO_printf(bio_err, "No signature to verify: use the -signature option\n");
26468651Skris		goto end;
26568651Skris	}
26668651Skris
26755714Skris	if ((argc > 0) && (argv[0][0] == '-')) /* bad option */
26855714Skris		{
26955714Skris		BIO_printf(bio_err,"unknown option '%s'\n",*argv);
27055714Skris		BIO_printf(bio_err,"options are\n");
27168651Skris		BIO_printf(bio_err,"-c              to output the digest with separating colons\n");
272238405Sjkim		BIO_printf(bio_err,"-r              to output the digest in coreutils format\n");
27368651Skris		BIO_printf(bio_err,"-d              to output debug info\n");
27468651Skris		BIO_printf(bio_err,"-hex            output as hex dump\n");
27568651Skris		BIO_printf(bio_err,"-binary         output in binary form\n");
276279264Sdelphij		BIO_printf(bio_err,"-hmac arg       set the HMAC key to arg\n");
277279264Sdelphij		BIO_printf(bio_err,"-non-fips-allow allow use of non FIPS digest\n");
27868651Skris		BIO_printf(bio_err,"-sign   file    sign digest using private key in file\n");
27968651Skris		BIO_printf(bio_err,"-verify file    verify a signature using public key in file\n");
28068651Skris		BIO_printf(bio_err,"-prverify file  verify a signature using private key in file\n");
281109998Smarkm		BIO_printf(bio_err,"-keyform arg    key file format (PEM or ENGINE)\n");
282238405Sjkim		BIO_printf(bio_err,"-out filename   output to filename rather than stdout\n");
28368651Skris		BIO_printf(bio_err,"-signature file signature to verify\n");
284238405Sjkim		BIO_printf(bio_err,"-sigopt nm:v    signature parameter\n");
285194206Ssimon		BIO_printf(bio_err,"-hmac key       create hashed MAC with key\n");
286238405Sjkim		BIO_printf(bio_err,"-mac algorithm  create MAC (not neccessarily HMAC)\n");
287238405Sjkim		BIO_printf(bio_err,"-macopt nm:v    MAC algorithm parameters or key\n");
288111147Snectar#ifndef OPENSSL_NO_ENGINE
289109998Smarkm		BIO_printf(bio_err,"-engine e       use engine e, possibly a hardware device.\n");
290111147Snectar#endif
29168651Skris
292238405Sjkim		EVP_MD_do_all_sorted(list_md_fn, bio_err);
29355714Skris		goto end;
29455714Skris		}
29568651Skris
29655714Skris	in=BIO_new(BIO_s_file());
29755714Skris	bmd=BIO_new(BIO_f_md());
29855714Skris	if (debug)
29955714Skris		{
30055714Skris		BIO_set_callback(in,BIO_debug_callback);
30155714Skris		/* needed for windows 3.1 */
302167612Ssimon		BIO_set_callback_arg(in,(char *)bio_err);
30355714Skris		}
30455714Skris
305160814Ssimon	if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
306160814Ssimon		{
307160814Ssimon		BIO_printf(bio_err, "Error getting password\n");
308160814Ssimon		goto end;
309160814Ssimon		}
310160814Ssimon
31155714Skris	if ((in == NULL) || (bmd == NULL))
31255714Skris		{
31355714Skris		ERR_print_errors(bio_err);
31455714Skris		goto end;
31555714Skris		}
31655714Skris
31768651Skris	if(out_bin == -1) {
318238405Sjkim		if(keyfile)
319238405Sjkim			out_bin = 1;
320238405Sjkim		else
321238405Sjkim			out_bin = 0;
32268651Skris	}
32368651Skris
32468651Skris	if(randfile)
32568651Skris		app_RAND_load_file(randfile, bio_err, 0);
32668651Skris
32768651Skris	if(outfile) {
32868651Skris		if(out_bin)
32968651Skris			out = BIO_new_file(outfile, "wb");
33068651Skris		else    out = BIO_new_file(outfile, "w");
33168651Skris	} else {
33268651Skris		out = BIO_new_fp(stdout, BIO_NOCLOSE);
333109998Smarkm#ifdef OPENSSL_SYS_VMS
33468651Skris		{
33568651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
33668651Skris		out = BIO_push(tmpbio, out);
33768651Skris		}
33868651Skris#endif
33968651Skris	}
34068651Skris
34168651Skris	if(!out) {
34268651Skris		BIO_printf(bio_err, "Error opening output file %s\n",
34368651Skris					outfile ? outfile : "(stdout)");
34468651Skris		ERR_print_errors(bio_err);
34568651Skris		goto end;
34668651Skris	}
347238405Sjkim	if ((!!mac_name + !!keyfile + !!hmac_key) > 1)
348238405Sjkim		{
349238405Sjkim		BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
350238405Sjkim		goto end;
351238405Sjkim		}
35268651Skris
353109998Smarkm	if(keyfile)
354109998Smarkm		{
355109998Smarkm		if (want_pub)
356109998Smarkm			sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL,
357109998Smarkm				e, "key file");
358109998Smarkm		else
359160814Ssimon			sigkey = load_key(bio_err, keyfile, keyform, 0, passin,
360109998Smarkm				e, "key file");
361109998Smarkm		if (!sigkey)
362109998Smarkm			{
363109998Smarkm			/* load_[pub]key() has already printed an appropriate
364109998Smarkm			   message */
36568651Skris			goto end;
366109998Smarkm			}
36768651Skris		}
36868651Skris
369238405Sjkim	if (mac_name)
370238405Sjkim		{
371238405Sjkim		EVP_PKEY_CTX *mac_ctx = NULL;
372238405Sjkim		int r = 0;
373238405Sjkim		if (!init_gen_str(bio_err, &mac_ctx, mac_name,e, 0))
374238405Sjkim			goto mac_end;
375238405Sjkim		if (macopts)
376238405Sjkim			{
377238405Sjkim			char *macopt;
378238405Sjkim			for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++)
379238405Sjkim				{
380238405Sjkim				macopt = sk_OPENSSL_STRING_value(macopts, i);
381238405Sjkim				if (pkey_ctrl_string(mac_ctx, macopt) <= 0)
382238405Sjkim					{
383238405Sjkim					BIO_printf(bio_err,
384238405Sjkim						"MAC parameter error \"%s\"\n",
385238405Sjkim						macopt);
386238405Sjkim					ERR_print_errors(bio_err);
387238405Sjkim					goto mac_end;
388238405Sjkim					}
389238405Sjkim				}
390238405Sjkim			}
391238405Sjkim		if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0)
392238405Sjkim			{
393238405Sjkim			BIO_puts(bio_err, "Error generating key\n");
394238405Sjkim			ERR_print_errors(bio_err);
395238405Sjkim			goto mac_end;
396238405Sjkim			}
397238405Sjkim		r = 1;
398238405Sjkim		mac_end:
399238405Sjkim		if (mac_ctx)
400238405Sjkim			EVP_PKEY_CTX_free(mac_ctx);
401238405Sjkim		if (r == 0)
402238405Sjkim			goto end;
403238405Sjkim		}
404238405Sjkim
405238405Sjkim	if (non_fips_allow)
406238405Sjkim		{
407238405Sjkim		EVP_MD_CTX *md_ctx;
408238405Sjkim		BIO_get_md_ctx(bmd,&md_ctx);
409238405Sjkim		EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
410238405Sjkim		}
411238405Sjkim
412238405Sjkim	if (hmac_key)
413238405Sjkim		{
414238405Sjkim		sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
415238405Sjkim					(unsigned char *)hmac_key, -1);
416238405Sjkim		if (!sigkey)
417238405Sjkim			goto end;
418238405Sjkim		}
419238405Sjkim
420238405Sjkim	if (sigkey)
421238405Sjkim		{
422238405Sjkim		EVP_MD_CTX *mctx = NULL;
423238405Sjkim		EVP_PKEY_CTX *pctx = NULL;
424238405Sjkim		int r;
425238405Sjkim		if (!BIO_get_md_ctx(bmd, &mctx))
426238405Sjkim			{
427238405Sjkim			BIO_printf(bio_err, "Error getting context\n");
428238405Sjkim			ERR_print_errors(bio_err);
429238405Sjkim			goto end;
430238405Sjkim			}
431238405Sjkim		if (do_verify)
432279264Sdelphij			r = EVP_DigestVerifyInit(mctx, &pctx, md, NULL, sigkey);
433238405Sjkim		else
434279264Sdelphij			r = EVP_DigestSignInit(mctx, &pctx, md, NULL, sigkey);
435238405Sjkim		if (!r)
436238405Sjkim			{
437238405Sjkim			BIO_printf(bio_err, "Error setting context\n");
438238405Sjkim			ERR_print_errors(bio_err);
439238405Sjkim			goto end;
440238405Sjkim			}
441238405Sjkim		if (sigopts)
442238405Sjkim			{
443238405Sjkim			char *sigopt;
444238405Sjkim			for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++)
445238405Sjkim				{
446238405Sjkim				sigopt = sk_OPENSSL_STRING_value(sigopts, i);
447238405Sjkim				if (pkey_ctrl_string(pctx, sigopt) <= 0)
448238405Sjkim					{
449238405Sjkim					BIO_printf(bio_err,
450238405Sjkim						"parameter error \"%s\"\n",
451238405Sjkim						sigopt);
452238405Sjkim					ERR_print_errors(bio_err);
453238405Sjkim					goto end;
454238405Sjkim					}
455238405Sjkim				}
456238405Sjkim			}
457238405Sjkim		}
458238405Sjkim	/* we use md as a filter, reading from 'in' */
459238405Sjkim	else
460238405Sjkim		{
461238405Sjkim		if (md == NULL)
462238405Sjkim			md = EVP_md5();
463238405Sjkim		if (!BIO_set_md(bmd,md))
464238405Sjkim			{
465238405Sjkim			BIO_printf(bio_err, "Error setting digest %s\n", pname);
466238405Sjkim			ERR_print_errors(bio_err);
467238405Sjkim			goto end;
468238405Sjkim			}
469238405Sjkim		}
470238405Sjkim
47168651Skris	if(sigfile && sigkey) {
47268651Skris		BIO *sigbio;
47368651Skris		sigbio = BIO_new_file(sigfile, "rb");
47468651Skris		siglen = EVP_PKEY_size(sigkey);
47568651Skris		sigbuf = OPENSSL_malloc(siglen);
47668651Skris		if(!sigbio) {
47768651Skris			BIO_printf(bio_err, "Error opening signature file %s\n",
47868651Skris								sigfile);
47968651Skris			ERR_print_errors(bio_err);
48068651Skris			goto end;
48168651Skris		}
48268651Skris		siglen = BIO_read(sigbio, sigbuf, siglen);
48368651Skris		BIO_free(sigbio);
48468651Skris		if(siglen <= 0) {
48568651Skris			BIO_printf(bio_err, "Error reading signature file %s\n",
48668651Skris								sigfile);
48768651Skris			ERR_print_errors(bio_err);
48868651Skris			goto end;
48968651Skris		}
49068651Skris	}
491238405Sjkim	inp=BIO_push(bmd,in);
49268651Skris
493238405Sjkim	if (md == NULL)
494194206Ssimon		{
495238405Sjkim		EVP_MD_CTX *tctx;
496238405Sjkim		BIO_get_md_ctx(bmd, &tctx);
497238405Sjkim		md = EVP_MD_CTX_md(tctx);
498194206Ssimon		}
499160814Ssimon
50055714Skris	if (argc == 0)
50155714Skris		{
50255714Skris		BIO_set_fp(in,stdin,BIO_NOCLOSE);
503109998Smarkm		err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf,
504238405Sjkim			  siglen,NULL,NULL,"stdin",bmd);
50555714Skris		}
50655714Skris	else
50755714Skris		{
508238405Sjkim		const char *md_name = NULL, *sig_name = NULL;
509238405Sjkim		if(!out_bin)
510238405Sjkim			{
511238405Sjkim			if (sigkey)
512238405Sjkim				{
513238405Sjkim				const EVP_PKEY_ASN1_METHOD *ameth;
514238405Sjkim				ameth = EVP_PKEY_get0_asn1(sigkey);
515238405Sjkim				if (ameth)
516238405Sjkim					EVP_PKEY_asn1_get0_info(NULL, NULL,
517238405Sjkim						NULL, NULL, &sig_name, ameth);
518238405Sjkim				}
519238405Sjkim			md_name = EVP_MD_name(md);
520238405Sjkim			}
521194206Ssimon		err = 0;
52255714Skris		for (i=0; i<argc; i++)
52355714Skris			{
524109998Smarkm			int r;
52555714Skris			if (BIO_read_filename(in,argv[i]) <= 0)
52655714Skris				{
52755714Skris				perror(argv[i]);
52855714Skris				err++;
52955714Skris				continue;
53055714Skris				}
531109998Smarkm			else
532109998Smarkm			r=do_fp(out,buf,inp,separator,out_bin,sigkey,sigbuf,
533238405Sjkim				siglen,sig_name,md_name, argv[i],bmd);
534109998Smarkm			if(r)
535109998Smarkm			    err=r;
53655714Skris			(void)BIO_reset(bmd);
53755714Skris			}
53855714Skris		}
53955714Skrisend:
54055714Skris	if (buf != NULL)
54155714Skris		{
542109998Smarkm		OPENSSL_cleanse(buf,BUFSIZE);
54368651Skris		OPENSSL_free(buf);
54455714Skris		}
54555714Skris	if (in != NULL) BIO_free(in);
546160814Ssimon	if (passin)
547160814Ssimon		OPENSSL_free(passin);
54868651Skris	BIO_free_all(out);
54968651Skris	EVP_PKEY_free(sigkey);
550238405Sjkim	if (sigopts)
551238405Sjkim		sk_OPENSSL_STRING_free(sigopts);
552238405Sjkim	if (macopts)
553238405Sjkim		sk_OPENSSL_STRING_free(macopts);
55468651Skris	if(sigbuf) OPENSSL_free(sigbuf);
55555714Skris	if (bmd != NULL) BIO_free(bmd);
556109998Smarkm	apps_shutdown();
557109998Smarkm	OPENSSL_EXIT(err);
55855714Skris	}
55955714Skris
560109998Smarkmint do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
561238405Sjkim	  EVP_PKEY *key, unsigned char *sigin, int siglen,
562238405Sjkim	  const char *sig_name, const char *md_name,
563238405Sjkim	  const char *file,BIO *bmd)
56455714Skris	{
565238405Sjkim	size_t len;
56655714Skris	int i;
56755714Skris
56855714Skris	for (;;)
56955714Skris		{
57055714Skris		i=BIO_read(bp,(char *)buf,BUFSIZE);
571109998Smarkm		if(i < 0)
572109998Smarkm			{
573109998Smarkm			BIO_printf(bio_err, "Read Error in %s\n",file);
574109998Smarkm			ERR_print_errors(bio_err);
575109998Smarkm			return 1;
576109998Smarkm			}
577109998Smarkm		if (i == 0) break;
57855714Skris		}
57968651Skris	if(sigin)
58068651Skris		{
58168651Skris		EVP_MD_CTX *ctx;
58268651Skris		BIO_get_md_ctx(bp, &ctx);
583238405Sjkim		i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
584109998Smarkm		if(i > 0)
585109998Smarkm			BIO_printf(out, "Verified OK\n");
586109998Smarkm		else if(i == 0)
587109998Smarkm			{
588109998Smarkm			BIO_printf(out, "Verification Failure\n");
589109998Smarkm			return 1;
590109998Smarkm			}
59168651Skris		else
59268651Skris			{
59368651Skris			BIO_printf(bio_err, "Error Verifying Data\n");
59468651Skris			ERR_print_errors(bio_err);
595109998Smarkm			return 1;
59668651Skris			}
597109998Smarkm		return 0;
59868651Skris		}
59968651Skris	if(key)
60068651Skris		{
60168651Skris		EVP_MD_CTX *ctx;
60268651Skris		BIO_get_md_ctx(bp, &ctx);
603238405Sjkim		len = BUFSIZE;
604238405Sjkim		if(!EVP_DigestSignFinal(ctx, buf, &len))
60568651Skris			{
60668651Skris			BIO_printf(bio_err, "Error Signing Data\n");
60768651Skris			ERR_print_errors(bio_err);
608109998Smarkm			return 1;
60968651Skris			}
61068651Skris		}
611238405Sjkim	else
612167612Ssimon		{
613238405Sjkim		len=BIO_gets(bp,(char *)buf,BUFSIZE);
614238405Sjkim		if ((int)len <0)
615238405Sjkim			{
616238405Sjkim			ERR_print_errors(bio_err);
617238405Sjkim			return 1;
618238405Sjkim			}
619167612Ssimon		}
62055714Skris
62168651Skris	if(binout) BIO_write(out, buf, len);
622238405Sjkim	else if (sep == 2)
623238405Sjkim		{
624238405Sjkim		for (i=0; i<(int)len; i++)
625238405Sjkim			BIO_printf(out, "%02x",buf[i]);
626238405Sjkim		BIO_printf(out, " *%s\n", file);
627238405Sjkim		}
62868651Skris	else
62955714Skris		{
630238405Sjkim		if (sig_name)
631238405Sjkim			BIO_printf(out, "%s-%s(%s)= ", sig_name, md_name, file);
632238405Sjkim		else if (md_name)
633238405Sjkim			BIO_printf(out, "%s(%s)= ", md_name, file);
634238405Sjkim		else
635238405Sjkim			BIO_printf(out, "(%s)= ", file);
636167612Ssimon		for (i=0; i<(int)len; i++)
63768651Skris			{
63868651Skris			if (sep && (i != 0))
63968651Skris				BIO_printf(out, ":");
64068651Skris			BIO_printf(out, "%02x",buf[i]);
64168651Skris			}
64268651Skris		BIO_printf(out, "\n");
64355714Skris		}
644109998Smarkm	return 0;
64555714Skris	}
64655714Skris
647