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.
8296341Sdelphij *
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).
15296341Sdelphij *
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.
22296341Sdelphij *
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 :-).
37296341Sdelphij * 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)"
40296341Sdelphij *
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.
52296341Sdelphij *
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
72296341Sdelphij#define BUFSIZE 1024*8
7355714Skris
7455714Skris#undef PROG
75296341Sdelphij#define PROG    dgst_main
7655714Skris
77109998Smarkmint do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
78296341Sdelphij          EVP_PKEY *key, unsigned char *sigin, int siglen,
79296341Sdelphij          const char *sig_name, const char *md_name,
80296341Sdelphij          const char *file, BIO *bmd);
8159191Skris
82238405Sjkimstatic void list_md_fn(const EVP_MD *m,
83296341Sdelphij                       const char *from, const char *to, void *arg)
84296341Sdelphij{
85296341Sdelphij    const char *mname;
86296341Sdelphij    /* Skip aliases */
87296341Sdelphij    if (!m)
88296341Sdelphij        return;
89296341Sdelphij    mname = OBJ_nid2ln(EVP_MD_type(m));
90296341Sdelphij    /* Skip shortnames */
91296341Sdelphij    if (strcmp(from, mname))
92296341Sdelphij        return;
93296341Sdelphij    /* Skip clones */
94296341Sdelphij    if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST)
95296341Sdelphij        return;
96296341Sdelphij    if (strchr(mname, ' '))
97296341Sdelphij        mname = EVP_MD_name(m);
98296341Sdelphij    BIO_printf(arg, "-%-14s to use the %s message digest algorithm\n",
99296341Sdelphij               mname, mname);
100296341Sdelphij}
101238405Sjkim
10259191Skrisint MAIN(int, char **);
10359191Skris
10455714Skrisint MAIN(int argc, char **argv)
105296341Sdelphij{
106296341Sdelphij    ENGINE *e = NULL;
107296341Sdelphij    unsigned char *buf = NULL;
108296341Sdelphij    int i, err = 1;
109296341Sdelphij    const EVP_MD *md = NULL, *m;
110296341Sdelphij    BIO *in = NULL, *inp;
111296341Sdelphij    BIO *bmd = NULL;
112296341Sdelphij    BIO *out = NULL;
113100928Snectar#define PROG_NAME_SIZE  39
114296341Sdelphij    char pname[PROG_NAME_SIZE + 1];
115296341Sdelphij    int separator = 0;
116296341Sdelphij    int debug = 0;
117296341Sdelphij    int keyform = FORMAT_PEM;
118296341Sdelphij    const char *outfile = NULL, *keyfile = NULL;
119296341Sdelphij    const char *sigfile = NULL, *randfile = NULL;
120296341Sdelphij    int out_bin = -1, want_pub = 0, do_verify = 0;
121296341Sdelphij    EVP_PKEY *sigkey = NULL;
122296341Sdelphij    unsigned char *sigbuf = NULL;
123296341Sdelphij    int siglen = 0;
124296341Sdelphij    char *passargin = NULL, *passin = NULL;
125111147Snectar#ifndef OPENSSL_NO_ENGINE
126296341Sdelphij    char *engine = NULL;
127111147Snectar#endif
128296341Sdelphij    char *hmac_key = NULL;
129296341Sdelphij    char *mac_name = NULL;
130296341Sdelphij    int non_fips_allow = 0;
131296341Sdelphij    STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
13255714Skris
133296341Sdelphij    apps_startup();
134238405Sjkim
135296341Sdelphij    if ((buf = (unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL) {
136296341Sdelphij        BIO_printf(bio_err, "out of memory\n");
137296341Sdelphij        goto end;
138296341Sdelphij    }
139296341Sdelphij    if (bio_err == NULL)
140296341Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
141296341Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
14255714Skris
143296341Sdelphij    if (!load_config(bio_err, NULL))
144296341Sdelphij        goto end;
145109998Smarkm
146296341Sdelphij    /* first check the program name */
147296341Sdelphij    program_name(argv[0], pname, sizeof pname);
14855714Skris
149296341Sdelphij    md = EVP_get_digestbyname(pname);
15055714Skris
151296341Sdelphij    argc--;
152296341Sdelphij    argv++;
153296341Sdelphij    while (argc > 0) {
154296341Sdelphij        if ((*argv)[0] != '-')
155296341Sdelphij            break;
156296341Sdelphij        if (strcmp(*argv, "-c") == 0)
157296341Sdelphij            separator = 1;
158296341Sdelphij        else if (strcmp(*argv, "-r") == 0)
159296341Sdelphij            separator = 2;
160296341Sdelphij        else if (strcmp(*argv, "-rand") == 0) {
161296341Sdelphij            if (--argc < 1)
162296341Sdelphij                break;
163296341Sdelphij            randfile = *(++argv);
164296341Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
165296341Sdelphij            if (--argc < 1)
166296341Sdelphij                break;
167296341Sdelphij            outfile = *(++argv);
168296341Sdelphij        } else if (strcmp(*argv, "-sign") == 0) {
169296341Sdelphij            if (--argc < 1)
170296341Sdelphij                break;
171296341Sdelphij            keyfile = *(++argv);
172296341Sdelphij        } else if (!strcmp(*argv, "-passin")) {
173296341Sdelphij            if (--argc < 1)
174296341Sdelphij                break;
175296341Sdelphij            passargin = *++argv;
176296341Sdelphij        } else if (strcmp(*argv, "-verify") == 0) {
177296341Sdelphij            if (--argc < 1)
178296341Sdelphij                break;
179296341Sdelphij            keyfile = *(++argv);
180296341Sdelphij            want_pub = 1;
181296341Sdelphij            do_verify = 1;
182296341Sdelphij        } else if (strcmp(*argv, "-prverify") == 0) {
183296341Sdelphij            if (--argc < 1)
184296341Sdelphij                break;
185296341Sdelphij            keyfile = *(++argv);
186296341Sdelphij            do_verify = 1;
187296341Sdelphij        } else if (strcmp(*argv, "-signature") == 0) {
188296341Sdelphij            if (--argc < 1)
189296341Sdelphij                break;
190296341Sdelphij            sigfile = *(++argv);
191296341Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
192296341Sdelphij            if (--argc < 1)
193296341Sdelphij                break;
194296341Sdelphij            keyform = str2fmt(*(++argv));
195296341Sdelphij        }
196111147Snectar#ifndef OPENSSL_NO_ENGINE
197296341Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
198296341Sdelphij            if (--argc < 1)
199296341Sdelphij                break;
200296341Sdelphij            engine = *(++argv);
201296341Sdelphij            e = setup_engine(bio_err, engine, 0);
202296341Sdelphij        }
203111147Snectar#endif
204296341Sdelphij        else if (strcmp(*argv, "-hex") == 0)
205296341Sdelphij            out_bin = 0;
206296341Sdelphij        else if (strcmp(*argv, "-binary") == 0)
207296341Sdelphij            out_bin = 1;
208296341Sdelphij        else if (strcmp(*argv, "-d") == 0)
209296341Sdelphij            debug = 1;
210296341Sdelphij        else if (!strcmp(*argv, "-fips-fingerprint"))
211296341Sdelphij            hmac_key = "etaonrishdlcupfm";
212296341Sdelphij        else if (strcmp(*argv, "-non-fips-allow") == 0)
213296341Sdelphij            non_fips_allow = 1;
214296341Sdelphij        else if (!strcmp(*argv, "-hmac")) {
215296341Sdelphij            if (--argc < 1)
216296341Sdelphij                break;
217296341Sdelphij            hmac_key = *++argv;
218296341Sdelphij        } else if (!strcmp(*argv, "-mac")) {
219296341Sdelphij            if (--argc < 1)
220296341Sdelphij                break;
221296341Sdelphij            mac_name = *++argv;
222296341Sdelphij        } else if (strcmp(*argv, "-sigopt") == 0) {
223296341Sdelphij            if (--argc < 1)
224296341Sdelphij                break;
225296341Sdelphij            if (!sigopts)
226296341Sdelphij                sigopts = sk_OPENSSL_STRING_new_null();
227296341Sdelphij            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
228296341Sdelphij                break;
229296341Sdelphij        } else if (strcmp(*argv, "-macopt") == 0) {
230296341Sdelphij            if (--argc < 1)
231296341Sdelphij                break;
232296341Sdelphij            if (!macopts)
233296341Sdelphij                macopts = sk_OPENSSL_STRING_new_null();
234296341Sdelphij            if (!macopts || !sk_OPENSSL_STRING_push(macopts, *(++argv)))
235296341Sdelphij                break;
236296341Sdelphij        } else if ((m = EVP_get_digestbyname(&((*argv)[1]))) != NULL)
237296341Sdelphij            md = m;
238296341Sdelphij        else
239296341Sdelphij            break;
240296341Sdelphij        argc--;
241296341Sdelphij        argv++;
242296341Sdelphij    }
24355714Skris
244296341Sdelphij    if (do_verify && !sigfile) {
245296341Sdelphij        BIO_printf(bio_err,
246296341Sdelphij                   "No signature to verify: use the -signature option\n");
247296341Sdelphij        goto end;
248296341Sdelphij    }
24955714Skris
250296341Sdelphij    if ((argc > 0) && (argv[0][0] == '-')) { /* bad option */
251296341Sdelphij        BIO_printf(bio_err, "unknown option '%s'\n", *argv);
252296341Sdelphij        BIO_printf(bio_err, "options are\n");
253296341Sdelphij        BIO_printf(bio_err,
254296341Sdelphij                   "-c              to output the digest with separating colons\n");
255296341Sdelphij        BIO_printf(bio_err,
256296341Sdelphij                   "-r              to output the digest in coreutils format\n");
257296341Sdelphij        BIO_printf(bio_err, "-d              to output debug info\n");
258296341Sdelphij        BIO_printf(bio_err, "-hex            output as hex dump\n");
259296341Sdelphij        BIO_printf(bio_err, "-binary         output in binary form\n");
260296341Sdelphij        BIO_printf(bio_err, "-hmac arg       set the HMAC key to arg\n");
261296341Sdelphij        BIO_printf(bio_err, "-non-fips-allow allow use of non FIPS digest\n");
262296341Sdelphij        BIO_printf(bio_err,
263296341Sdelphij                   "-sign   file    sign digest using private key in file\n");
264296341Sdelphij        BIO_printf(bio_err,
265296341Sdelphij                   "-verify file    verify a signature using public key in file\n");
266296341Sdelphij        BIO_printf(bio_err,
267296341Sdelphij                   "-prverify file  verify a signature using private key in file\n");
268296341Sdelphij        BIO_printf(bio_err,
269296341Sdelphij                   "-keyform arg    key file format (PEM or ENGINE)\n");
270296341Sdelphij        BIO_printf(bio_err,
271296341Sdelphij                   "-out filename   output to filename rather than stdout\n");
272296341Sdelphij        BIO_printf(bio_err, "-signature file signature to verify\n");
273296341Sdelphij        BIO_printf(bio_err, "-sigopt nm:v    signature parameter\n");
274296341Sdelphij        BIO_printf(bio_err, "-hmac key       create hashed MAC with key\n");
275296341Sdelphij        BIO_printf(bio_err,
276296341Sdelphij                   "-mac algorithm  create MAC (not neccessarily HMAC)\n");
277296341Sdelphij        BIO_printf(bio_err,
278296341Sdelphij                   "-macopt nm:v    MAC algorithm parameters or key\n");
279111147Snectar#ifndef OPENSSL_NO_ENGINE
280296341Sdelphij        BIO_printf(bio_err,
281296341Sdelphij                   "-engine e       use engine e, possibly a hardware device.\n");
282111147Snectar#endif
28368651Skris
284296341Sdelphij        EVP_MD_do_all_sorted(list_md_fn, bio_err);
285296341Sdelphij        goto end;
286296341Sdelphij    }
28768651Skris
288296341Sdelphij    in = BIO_new(BIO_s_file());
289296341Sdelphij    bmd = BIO_new(BIO_f_md());
290296341Sdelphij    if ((in == NULL) || (bmd == NULL)) {
291296341Sdelphij        ERR_print_errors(bio_err);
292296341Sdelphij        goto end;
293296341Sdelphij    }
29455714Skris
295296341Sdelphij    if (debug) {
296296341Sdelphij        BIO_set_callback(in, BIO_debug_callback);
297296341Sdelphij        /* needed for windows 3.1 */
298296341Sdelphij        BIO_set_callback_arg(in, (char *)bio_err);
299296341Sdelphij    }
300160814Ssimon
301296341Sdelphij    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
302296341Sdelphij        BIO_printf(bio_err, "Error getting password\n");
303296341Sdelphij        goto end;
304296341Sdelphij    }
30555714Skris
306296341Sdelphij    if (out_bin == -1) {
307296341Sdelphij        if (keyfile)
308296341Sdelphij            out_bin = 1;
309296341Sdelphij        else
310296341Sdelphij            out_bin = 0;
311296341Sdelphij    }
31268651Skris
313296341Sdelphij    if (randfile)
314296341Sdelphij        app_RAND_load_file(randfile, bio_err, 0);
31568651Skris
316296341Sdelphij    if (outfile) {
317296341Sdelphij        if (out_bin)
318296341Sdelphij            out = BIO_new_file(outfile, "wb");
319296341Sdelphij        else
320296341Sdelphij            out = BIO_new_file(outfile, "w");
321296341Sdelphij    } else {
322296341Sdelphij        out = BIO_new_fp(stdout, BIO_NOCLOSE);
323109998Smarkm#ifdef OPENSSL_SYS_VMS
324296341Sdelphij        {
325296341Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
326296341Sdelphij            out = BIO_push(tmpbio, out);
327296341Sdelphij        }
32868651Skris#endif
329296341Sdelphij    }
33068651Skris
331296341Sdelphij    if (!out) {
332296341Sdelphij        BIO_printf(bio_err, "Error opening output file %s\n",
333296341Sdelphij                   outfile ? outfile : "(stdout)");
334296341Sdelphij        ERR_print_errors(bio_err);
335296341Sdelphij        goto end;
336296341Sdelphij    }
337296341Sdelphij    if ((! !mac_name + ! !keyfile + ! !hmac_key) > 1) {
338296341Sdelphij        BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
339296341Sdelphij        goto end;
340296341Sdelphij    }
34168651Skris
342296341Sdelphij    if (keyfile) {
343296341Sdelphij        if (want_pub)
344296341Sdelphij            sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL,
345296341Sdelphij                                 e, "key file");
346296341Sdelphij        else
347296341Sdelphij            sigkey = load_key(bio_err, keyfile, keyform, 0, passin,
348296341Sdelphij                              e, "key file");
349296341Sdelphij        if (!sigkey) {
350296341Sdelphij            /*
351296341Sdelphij             * load_[pub]key() has already printed an appropriate message
352296341Sdelphij             */
353296341Sdelphij            goto end;
354296341Sdelphij        }
355296341Sdelphij    }
35668651Skris
357296341Sdelphij    if (mac_name) {
358296341Sdelphij        EVP_PKEY_CTX *mac_ctx = NULL;
359296341Sdelphij        int r = 0;
360296341Sdelphij        if (!init_gen_str(bio_err, &mac_ctx, mac_name, e, 0))
361296341Sdelphij            goto mac_end;
362296341Sdelphij        if (macopts) {
363296341Sdelphij            char *macopt;
364296341Sdelphij            for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
365296341Sdelphij                macopt = sk_OPENSSL_STRING_value(macopts, i);
366296341Sdelphij                if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
367296341Sdelphij                    BIO_printf(bio_err,
368296341Sdelphij                               "MAC parameter error \"%s\"\n", macopt);
369296341Sdelphij                    ERR_print_errors(bio_err);
370296341Sdelphij                    goto mac_end;
371296341Sdelphij                }
372296341Sdelphij            }
373296341Sdelphij        }
374296341Sdelphij        if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
375296341Sdelphij            BIO_puts(bio_err, "Error generating key\n");
376296341Sdelphij            ERR_print_errors(bio_err);
377296341Sdelphij            goto mac_end;
378296341Sdelphij        }
379296341Sdelphij        r = 1;
380296341Sdelphij mac_end:
381296341Sdelphij        if (mac_ctx)
382296341Sdelphij            EVP_PKEY_CTX_free(mac_ctx);
383296341Sdelphij        if (r == 0)
384296341Sdelphij            goto end;
385296341Sdelphij    }
386238405Sjkim
387296341Sdelphij    if (non_fips_allow) {
388296341Sdelphij        EVP_MD_CTX *md_ctx;
389296341Sdelphij        BIO_get_md_ctx(bmd, &md_ctx);
390296341Sdelphij        EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
391296341Sdelphij    }
392238405Sjkim
393296341Sdelphij    if (hmac_key) {
394296341Sdelphij        sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
395296341Sdelphij                                      (unsigned char *)hmac_key, -1);
396296341Sdelphij        if (!sigkey)
397296341Sdelphij            goto end;
398296341Sdelphij    }
399238405Sjkim
400296341Sdelphij    if (sigkey) {
401296341Sdelphij        EVP_MD_CTX *mctx = NULL;
402296341Sdelphij        EVP_PKEY_CTX *pctx = NULL;
403296341Sdelphij        int r;
404296341Sdelphij        if (!BIO_get_md_ctx(bmd, &mctx)) {
405296341Sdelphij            BIO_printf(bio_err, "Error getting context\n");
406296341Sdelphij            ERR_print_errors(bio_err);
407296341Sdelphij            goto end;
408296341Sdelphij        }
409296341Sdelphij        if (do_verify)
410296341Sdelphij            r = EVP_DigestVerifyInit(mctx, &pctx, md, NULL, sigkey);
411296341Sdelphij        else
412296341Sdelphij            r = EVP_DigestSignInit(mctx, &pctx, md, NULL, sigkey);
413296341Sdelphij        if (!r) {
414296341Sdelphij            BIO_printf(bio_err, "Error setting context\n");
415296341Sdelphij            ERR_print_errors(bio_err);
416296341Sdelphij            goto end;
417296341Sdelphij        }
418296341Sdelphij        if (sigopts) {
419296341Sdelphij            char *sigopt;
420296341Sdelphij            for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
421296341Sdelphij                sigopt = sk_OPENSSL_STRING_value(sigopts, i);
422296341Sdelphij                if (pkey_ctrl_string(pctx, sigopt) <= 0) {
423296341Sdelphij                    BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
424296341Sdelphij                    ERR_print_errors(bio_err);
425296341Sdelphij                    goto end;
426296341Sdelphij                }
427296341Sdelphij            }
428296341Sdelphij        }
429296341Sdelphij    }
430296341Sdelphij    /* we use md as a filter, reading from 'in' */
431296341Sdelphij    else {
432296341Sdelphij        if (md == NULL)
433296341Sdelphij            md = EVP_md5();
434296341Sdelphij        if (!BIO_set_md(bmd, md)) {
435296341Sdelphij            BIO_printf(bio_err, "Error setting digest %s\n", pname);
436296341Sdelphij            ERR_print_errors(bio_err);
437296341Sdelphij            goto end;
438296341Sdelphij        }
439296341Sdelphij    }
440238405Sjkim
441296341Sdelphij    if (sigfile && sigkey) {
442296341Sdelphij        BIO *sigbio;
443296341Sdelphij        sigbio = BIO_new_file(sigfile, "rb");
444296341Sdelphij        siglen = EVP_PKEY_size(sigkey);
445296341Sdelphij        sigbuf = OPENSSL_malloc(siglen);
446296341Sdelphij        if (!sigbio) {
447296341Sdelphij            BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
448296341Sdelphij            ERR_print_errors(bio_err);
449296341Sdelphij            goto end;
450296341Sdelphij        }
451296341Sdelphij        if (!sigbuf) {
452296341Sdelphij            BIO_printf(bio_err, "Out of memory\n");
453296341Sdelphij            ERR_print_errors(bio_err);
454296341Sdelphij            goto end;
455296341Sdelphij        }
456296341Sdelphij        siglen = BIO_read(sigbio, sigbuf, siglen);
457296341Sdelphij        BIO_free(sigbio);
458296341Sdelphij        if (siglen <= 0) {
459296341Sdelphij            BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
460296341Sdelphij            ERR_print_errors(bio_err);
461296341Sdelphij            goto end;
462296341Sdelphij        }
463296341Sdelphij    }
464296341Sdelphij    inp = BIO_push(bmd, in);
46568651Skris
466296341Sdelphij    if (md == NULL) {
467296341Sdelphij        EVP_MD_CTX *tctx;
468296341Sdelphij        BIO_get_md_ctx(bmd, &tctx);
469296341Sdelphij        md = EVP_MD_CTX_md(tctx);
470296341Sdelphij    }
471160814Ssimon
472296341Sdelphij    if (argc == 0) {
473296341Sdelphij        BIO_set_fp(in, stdin, BIO_NOCLOSE);
474296341Sdelphij        err = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
475296341Sdelphij                    siglen, NULL, NULL, "stdin", bmd);
476296341Sdelphij    } else {
477296341Sdelphij        const char *md_name = NULL, *sig_name = NULL;
478296341Sdelphij        if (!out_bin) {
479296341Sdelphij            if (sigkey) {
480296341Sdelphij                const EVP_PKEY_ASN1_METHOD *ameth;
481296341Sdelphij                ameth = EVP_PKEY_get0_asn1(sigkey);
482296341Sdelphij                if (ameth)
483296341Sdelphij                    EVP_PKEY_asn1_get0_info(NULL, NULL,
484296341Sdelphij                                            NULL, NULL, &sig_name, ameth);
485296341Sdelphij            }
486296341Sdelphij            md_name = EVP_MD_name(md);
487296341Sdelphij        }
488296341Sdelphij        err = 0;
489296341Sdelphij        for (i = 0; i < argc; i++) {
490296341Sdelphij            int r;
491296341Sdelphij            if (BIO_read_filename(in, argv[i]) <= 0) {
492296341Sdelphij                perror(argv[i]);
493296341Sdelphij                err++;
494296341Sdelphij                continue;
495296341Sdelphij            } else
496296341Sdelphij                r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
497296341Sdelphij                          siglen, sig_name, md_name, argv[i], bmd);
498296341Sdelphij            if (r)
499296341Sdelphij                err = r;
500296341Sdelphij            (void)BIO_reset(bmd);
501296341Sdelphij        }
502296341Sdelphij    }
503296341Sdelphij end:
504296341Sdelphij    if (buf != NULL) {
505296341Sdelphij        OPENSSL_cleanse(buf, BUFSIZE);
506296341Sdelphij        OPENSSL_free(buf);
507296341Sdelphij    }
508296341Sdelphij    if (in != NULL)
509296341Sdelphij        BIO_free(in);
510296341Sdelphij    if (passin)
511296341Sdelphij        OPENSSL_free(passin);
512296341Sdelphij    BIO_free_all(out);
513296341Sdelphij    EVP_PKEY_free(sigkey);
514296341Sdelphij    if (sigopts)
515296341Sdelphij        sk_OPENSSL_STRING_free(sigopts);
516296341Sdelphij    if (macopts)
517296341Sdelphij        sk_OPENSSL_STRING_free(macopts);
518296341Sdelphij    if (sigbuf)
519296341Sdelphij        OPENSSL_free(sigbuf);
520296341Sdelphij    if (bmd != NULL)
521296341Sdelphij        BIO_free(bmd);
522296341Sdelphij    apps_shutdown();
523296341Sdelphij    OPENSSL_EXIT(err);
524296341Sdelphij}
52555714Skris
526109998Smarkmint do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
527296341Sdelphij          EVP_PKEY *key, unsigned char *sigin, int siglen,
528296341Sdelphij          const char *sig_name, const char *md_name,
529296341Sdelphij          const char *file, BIO *bmd)
530296341Sdelphij{
531296341Sdelphij    size_t len;
532296341Sdelphij    int i;
53355714Skris
534296341Sdelphij    for (;;) {
535296341Sdelphij        i = BIO_read(bp, (char *)buf, BUFSIZE);
536296341Sdelphij        if (i < 0) {
537296341Sdelphij            BIO_printf(bio_err, "Read Error in %s\n", file);
538296341Sdelphij            ERR_print_errors(bio_err);
539296341Sdelphij            return 1;
540296341Sdelphij        }
541296341Sdelphij        if (i == 0)
542296341Sdelphij            break;
543296341Sdelphij    }
544296341Sdelphij    if (sigin) {
545296341Sdelphij        EVP_MD_CTX *ctx;
546296341Sdelphij        BIO_get_md_ctx(bp, &ctx);
547296341Sdelphij        i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
548296341Sdelphij        if (i > 0)
549296341Sdelphij            BIO_printf(out, "Verified OK\n");
550296341Sdelphij        else if (i == 0) {
551296341Sdelphij            BIO_printf(out, "Verification Failure\n");
552296341Sdelphij            return 1;
553296341Sdelphij        } else {
554296341Sdelphij            BIO_printf(bio_err, "Error Verifying Data\n");
555296341Sdelphij            ERR_print_errors(bio_err);
556296341Sdelphij            return 1;
557296341Sdelphij        }
558296341Sdelphij        return 0;
559296341Sdelphij    }
560296341Sdelphij    if (key) {
561296341Sdelphij        EVP_MD_CTX *ctx;
562296341Sdelphij        BIO_get_md_ctx(bp, &ctx);
563296341Sdelphij        len = BUFSIZE;
564296341Sdelphij        if (!EVP_DigestSignFinal(ctx, buf, &len)) {
565296341Sdelphij            BIO_printf(bio_err, "Error Signing Data\n");
566296341Sdelphij            ERR_print_errors(bio_err);
567296341Sdelphij            return 1;
568296341Sdelphij        }
569296341Sdelphij    } else {
570296341Sdelphij        len = BIO_gets(bp, (char *)buf, BUFSIZE);
571296341Sdelphij        if ((int)len < 0) {
572296341Sdelphij            ERR_print_errors(bio_err);
573296341Sdelphij            return 1;
574296341Sdelphij        }
575296341Sdelphij    }
57655714Skris
577296341Sdelphij    if (binout)
578296341Sdelphij        BIO_write(out, buf, len);
579296341Sdelphij    else if (sep == 2) {
580296341Sdelphij        for (i = 0; i < (int)len; i++)
581296341Sdelphij            BIO_printf(out, "%02x", buf[i]);
582296341Sdelphij        BIO_printf(out, " *%s\n", file);
583296341Sdelphij    } else {
584296341Sdelphij        if (sig_name)
585296341Sdelphij            BIO_printf(out, "%s-%s(%s)= ", sig_name, md_name, file);
586296341Sdelphij        else if (md_name)
587296341Sdelphij            BIO_printf(out, "%s(%s)= ", md_name, file);
588296341Sdelphij        else
589296341Sdelphij            BIO_printf(out, "(%s)= ", file);
590296341Sdelphij        for (i = 0; i < (int)len; i++) {
591296341Sdelphij            if (sep && (i != 0))
592296341Sdelphij                BIO_printf(out, ":");
593296341Sdelphij            BIO_printf(out, "%02x", buf[i]);
594296341Sdelphij        }
595296341Sdelphij        BIO_printf(out, "\n");
596296341Sdelphij    }
597296341Sdelphij    return 0;
598296341Sdelphij}
599