dgst.c revision 100928
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>
6955714Skris
7055714Skris#undef BUFSIZE
7155714Skris#define BUFSIZE	1024*8
7255714Skris
7355714Skris#undef PROG
7455714Skris#define PROG	dgst_main
7555714Skris
7679998Skrisvoid do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
7768651Skris		EVP_PKEY *key, unsigned char *sigin, int siglen);
7859191Skris
7959191Skrisint MAIN(int, char **);
8059191Skris
8155714Skrisint MAIN(int argc, char **argv)
8255714Skris	{
8355714Skris	unsigned char *buf=NULL;
8455714Skris	int i,err=0;
8555714Skris	const EVP_MD *md=NULL,*m;
8655714Skris	BIO *in=NULL,*inp;
8755714Skris	BIO *bmd=NULL;
8868651Skris	BIO *out = NULL;
8955714Skris	const char *name;
90100928Snectar#define PROG_NAME_SIZE  39
91100928Snectar	char pname[PROG_NAME_SIZE+1];
9255714Skris	int separator=0;
9355714Skris	int debug=0;
9468651Skris	const char *outfile = NULL, *keyfile = NULL;
9568651Skris	const char *sigfile = NULL, *randfile = NULL;
9679998Skris	int out_bin = -1, want_pub = 0, do_verify = 0;
9768651Skris	EVP_PKEY *sigkey = NULL;
9868651Skris	unsigned char *sigbuf = NULL;
9968651Skris	int siglen = 0;
10055714Skris
10155714Skris	apps_startup();
10255714Skris
10368651Skris	if ((buf=(unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL)
10455714Skris		{
10555714Skris		BIO_printf(bio_err,"out of memory\n");
10655714Skris		goto end;
10755714Skris		}
10855714Skris	if (bio_err == NULL)
10955714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
11055714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
11155714Skris
11255714Skris	/* first check the program name */
11355714Skris	program_name(argv[0],pname,PROG_NAME_SIZE);
11455714Skris
11555714Skris	md=EVP_get_digestbyname(pname);
11655714Skris
11755714Skris	argc--;
11855714Skris	argv++;
11955714Skris	while (argc > 0)
12055714Skris		{
12155714Skris		if ((*argv)[0] != '-') break;
12255714Skris		if (strcmp(*argv,"-c") == 0)
12355714Skris			separator=1;
12468651Skris		else if (strcmp(*argv,"-rand") == 0)
12568651Skris			{
12668651Skris			if (--argc < 1) break;
12768651Skris			randfile=*(++argv);
12868651Skris			}
12968651Skris		else if (strcmp(*argv,"-out") == 0)
13068651Skris			{
13168651Skris			if (--argc < 1) break;
13268651Skris			outfile=*(++argv);
13368651Skris			}
13468651Skris		else if (strcmp(*argv,"-sign") == 0)
13568651Skris			{
13668651Skris			if (--argc < 1) break;
13768651Skris			keyfile=*(++argv);
13868651Skris			}
13968651Skris		else if (strcmp(*argv,"-verify") == 0)
14068651Skris			{
14168651Skris			if (--argc < 1) break;
14268651Skris			keyfile=*(++argv);
14368651Skris			want_pub = 1;
14468651Skris			do_verify = 1;
14568651Skris			}
14668651Skris		else if (strcmp(*argv,"-prverify") == 0)
14768651Skris			{
14868651Skris			if (--argc < 1) break;
14968651Skris			keyfile=*(++argv);
15068651Skris			do_verify = 1;
15168651Skris			}
15268651Skris		else if (strcmp(*argv,"-signature") == 0)
15368651Skris			{
15468651Skris			if (--argc < 1) break;
15568651Skris			sigfile=*(++argv);
15668651Skris			}
15768651Skris		else if (strcmp(*argv,"-hex") == 0)
15868651Skris			out_bin = 0;
15968651Skris		else if (strcmp(*argv,"-binary") == 0)
16068651Skris			out_bin = 1;
16155714Skris		else if (strcmp(*argv,"-d") == 0)
16255714Skris			debug=1;
16355714Skris		else if ((m=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
16455714Skris			md=m;
16555714Skris		else
16655714Skris			break;
16755714Skris		argc--;
16855714Skris		argv++;
16955714Skris		}
17055714Skris
17155714Skris	if (md == NULL)
17255714Skris		md=EVP_md5();
17355714Skris
17468651Skris	if(do_verify && !sigfile) {
17568651Skris		BIO_printf(bio_err, "No signature to verify: use the -signature option\n");
17668651Skris		err = 1;
17768651Skris		goto end;
17868651Skris	}
17968651Skris
18055714Skris	if ((argc > 0) && (argv[0][0] == '-')) /* bad option */
18155714Skris		{
18255714Skris		BIO_printf(bio_err,"unknown option '%s'\n",*argv);
18355714Skris		BIO_printf(bio_err,"options are\n");
18468651Skris		BIO_printf(bio_err,"-c              to output the digest with separating colons\n");
18568651Skris		BIO_printf(bio_err,"-d              to output debug info\n");
18668651Skris		BIO_printf(bio_err,"-hex            output as hex dump\n");
18768651Skris		BIO_printf(bio_err,"-binary         output in binary form\n");
18868651Skris		BIO_printf(bio_err,"-sign   file    sign digest using private key in file\n");
18968651Skris		BIO_printf(bio_err,"-verify file    verify a signature using public key in file\n");
19068651Skris		BIO_printf(bio_err,"-prverify file  verify a signature using private key in file\n");
19168651Skris		BIO_printf(bio_err,"-signature file signature to verify\n");
19268651Skris		BIO_printf(bio_err,"-binary         output in binary form\n");
19368651Skris
19455714Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm (default)\n",
19555714Skris			LN_md5,LN_md5);
19655714Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
19768651Skris			LN_md4,LN_md4);
19868651Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
19955714Skris			LN_md2,LN_md2);
20055714Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
20155714Skris			LN_sha1,LN_sha1);
20255714Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
20355714Skris			LN_sha,LN_sha);
20455714Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
20555714Skris			LN_mdc2,LN_mdc2);
20655714Skris		BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
20755714Skris			LN_ripemd160,LN_ripemd160);
20855714Skris		err=1;
20955714Skris		goto end;
21055714Skris		}
21168651Skris
21255714Skris	in=BIO_new(BIO_s_file());
21355714Skris	bmd=BIO_new(BIO_f_md());
21455714Skris	if (debug)
21555714Skris		{
21655714Skris		BIO_set_callback(in,BIO_debug_callback);
21755714Skris		/* needed for windows 3.1 */
21855714Skris		BIO_set_callback_arg(in,bio_err);
21955714Skris		}
22055714Skris
22155714Skris	if ((in == NULL) || (bmd == NULL))
22255714Skris		{
22355714Skris		ERR_print_errors(bio_err);
22455714Skris		goto end;
22555714Skris		}
22655714Skris
22768651Skris	if(out_bin == -1) {
22868651Skris		if(keyfile) out_bin = 1;
22968651Skris		else out_bin = 0;
23068651Skris	}
23168651Skris
23268651Skris	if(randfile)
23368651Skris		app_RAND_load_file(randfile, bio_err, 0);
23468651Skris
23568651Skris	if(outfile) {
23668651Skris		if(out_bin)
23768651Skris			out = BIO_new_file(outfile, "wb");
23868651Skris		else    out = BIO_new_file(outfile, "w");
23968651Skris	} else {
24068651Skris		out = BIO_new_fp(stdout, BIO_NOCLOSE);
24168651Skris#ifdef VMS
24268651Skris		{
24368651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
24468651Skris		out = BIO_push(tmpbio, out);
24568651Skris		}
24668651Skris#endif
24768651Skris	}
24868651Skris
24968651Skris	if(!out) {
25068651Skris		BIO_printf(bio_err, "Error opening output file %s\n",
25168651Skris					outfile ? outfile : "(stdout)");
25268651Skris		ERR_print_errors(bio_err);
25368651Skris		goto end;
25468651Skris	}
25568651Skris
25668651Skris	if(keyfile) {
25768651Skris		BIO *keybio;
25868651Skris		keybio = BIO_new_file(keyfile, "r");
25968651Skris		if(!keybio) {
26068651Skris			BIO_printf(bio_err, "Error opening key file %s\n",
26168651Skris								keyfile);
26268651Skris			ERR_print_errors(bio_err);
26368651Skris			goto end;
26468651Skris		}
26568651Skris
26668651Skris		if(want_pub)
26768651Skris			sigkey = PEM_read_bio_PUBKEY(keybio, NULL, NULL, NULL);
26868651Skris		else sigkey = PEM_read_bio_PrivateKey(keybio, NULL, NULL, NULL);
26968651Skris		BIO_free(keybio);
27068651Skris		if(!sigkey) {
27168651Skris			BIO_printf(bio_err, "Error reading key file %s\n",
27268651Skris								keyfile);
27368651Skris			ERR_print_errors(bio_err);
27468651Skris			goto end;
27568651Skris		}
27668651Skris	}
27768651Skris
27868651Skris	if(sigfile && sigkey) {
27968651Skris		BIO *sigbio;
28068651Skris		sigbio = BIO_new_file(sigfile, "rb");
28168651Skris		siglen = EVP_PKEY_size(sigkey);
28268651Skris		sigbuf = OPENSSL_malloc(siglen);
28368651Skris		if(!sigbio) {
28468651Skris			BIO_printf(bio_err, "Error opening signature file %s\n",
28568651Skris								sigfile);
28668651Skris			ERR_print_errors(bio_err);
28768651Skris			goto end;
28868651Skris		}
28968651Skris		siglen = BIO_read(sigbio, sigbuf, siglen);
29068651Skris		BIO_free(sigbio);
29168651Skris		if(siglen <= 0) {
29268651Skris			BIO_printf(bio_err, "Error reading signature file %s\n",
29368651Skris								sigfile);
29468651Skris			ERR_print_errors(bio_err);
29568651Skris			goto end;
29668651Skris		}
29768651Skris	}
29868651Skris
29968651Skris
30068651Skris
30155714Skris	/* we use md as a filter, reading from 'in' */
30255714Skris	BIO_set_md(bmd,md);
30355714Skris	inp=BIO_push(bmd,in);
30455714Skris
30555714Skris	if (argc == 0)
30655714Skris		{
30755714Skris		BIO_set_fp(in,stdin,BIO_NOCLOSE);
30868651Skris		do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf, siglen);
30955714Skris		}
31055714Skris	else
31155714Skris		{
31255714Skris		name=OBJ_nid2sn(md->type);
31355714Skris		for (i=0; i<argc; i++)
31455714Skris			{
31555714Skris			if (BIO_read_filename(in,argv[i]) <= 0)
31655714Skris				{
31755714Skris				perror(argv[i]);
31855714Skris				err++;
31955714Skris				continue;
32055714Skris				}
32168651Skris			if(!out_bin) BIO_printf(out, "%s(%s)= ",name,argv[i]);
32268651Skris			do_fp(out, buf,inp,separator, out_bin, sigkey,
32368651Skris								sigbuf, siglen);
32455714Skris			(void)BIO_reset(bmd);
32555714Skris			}
32655714Skris		}
32755714Skrisend:
32855714Skris	if (buf != NULL)
32955714Skris		{
33055714Skris		memset(buf,0,BUFSIZE);
33168651Skris		OPENSSL_free(buf);
33255714Skris		}
33355714Skris	if (in != NULL) BIO_free(in);
33468651Skris	BIO_free_all(out);
33568651Skris	EVP_PKEY_free(sigkey);
33668651Skris	if(sigbuf) OPENSSL_free(sigbuf);
33755714Skris	if (bmd != NULL) BIO_free(bmd);
33855714Skris	EXIT(err);
33955714Skris	}
34055714Skris
34179998Skrisvoid do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
34268651Skris			EVP_PKEY *key, unsigned char *sigin, int siglen)
34355714Skris	{
34455714Skris	int len;
34555714Skris	int i;
34655714Skris
34755714Skris	for (;;)
34855714Skris		{
34955714Skris		i=BIO_read(bp,(char *)buf,BUFSIZE);
35055714Skris		if (i <= 0) break;
35155714Skris		}
35268651Skris	if(sigin)
35368651Skris		{
35468651Skris		EVP_MD_CTX *ctx;
35568651Skris		BIO_get_md_ctx(bp, &ctx);
35668651Skris		i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key);
35768651Skris		if(i > 0) BIO_printf(out, "Verified OK\n");
35868651Skris		else if(i == 0) BIO_printf(out, "Verification Failure\n");
35968651Skris		else
36068651Skris			{
36168651Skris			BIO_printf(bio_err, "Error Verifying Data\n");
36268651Skris			ERR_print_errors(bio_err);
36368651Skris			}
36468651Skris		return;
36568651Skris		}
36668651Skris	if(key)
36768651Skris		{
36868651Skris		EVP_MD_CTX *ctx;
36968651Skris		BIO_get_md_ctx(bp, &ctx);
37068651Skris		if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key))
37168651Skris			{
37268651Skris			BIO_printf(bio_err, "Error Signing Data\n");
37368651Skris			ERR_print_errors(bio_err);
37468651Skris			return;
37568651Skris			}
37668651Skris		}
37768651Skris	else
37868651Skris		len=BIO_gets(bp,(char *)buf,BUFSIZE);
37955714Skris
38068651Skris	if(binout) BIO_write(out, buf, len);
38168651Skris	else
38255714Skris		{
38368651Skris		for (i=0; i<len; i++)
38468651Skris			{
38568651Skris			if (sep && (i != 0))
38668651Skris				BIO_printf(out, ":");
38768651Skris			BIO_printf(out, "%02x",buf[i]);
38868651Skris			}
38968651Skris		BIO_printf(out, "\n");
39055714Skris		}
39155714Skris	}
39255714Skris
393