source: trunk/third/openssl/apps/dgst.c @ 18442

Revision 18442, 11.5 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18441, which included commits to RCS files with non-trunk default branches.
Line 
1/* apps/dgst.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <string.h>
61#include <stdlib.h>
62#include "apps.h"
63#include <openssl/bio.h>
64#include <openssl/err.h>
65#include <openssl/evp.h>
66#include <openssl/objects.h>
67#include <openssl/x509.h>
68#include <openssl/pem.h>
69
70#undef BUFSIZE
71#define BUFSIZE 1024*8
72
73#undef PROG
74#define PROG    dgst_main
75
76int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
77          EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title,
78          const char *file);
79
80int MAIN(int, char **);
81
82int MAIN(int argc, char **argv)
83        {
84        ENGINE *e = NULL;
85        unsigned char *buf=NULL;
86        int i,err=0;
87        const EVP_MD *md=NULL,*m;
88        BIO *in=NULL,*inp;
89        BIO *bmd=NULL;
90        BIO *out = NULL;
91        const char *name;
92#define PROG_NAME_SIZE  39
93        char pname[PROG_NAME_SIZE+1];
94        int separator=0;
95        int debug=0;
96        int keyform=FORMAT_PEM;
97        const char *outfile = NULL, *keyfile = NULL;
98        const char *sigfile = NULL, *randfile = NULL;
99        int out_bin = -1, want_pub = 0, do_verify = 0;
100        EVP_PKEY *sigkey = NULL;
101        unsigned char *sigbuf = NULL;
102        int siglen = 0;
103        char *engine=NULL;
104
105        apps_startup();
106
107        if ((buf=(unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL)
108                {
109                BIO_printf(bio_err,"out of memory\n");
110                goto end;
111                }
112        if (bio_err == NULL)
113                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
114                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
115
116        if (!load_config(bio_err, NULL))
117                goto end;
118
119        /* first check the program name */
120        program_name(argv[0],pname,sizeof pname);
121
122        md=EVP_get_digestbyname(pname);
123
124        argc--;
125        argv++;
126        while (argc > 0)
127                {
128                if ((*argv)[0] != '-') break;
129                if (strcmp(*argv,"-c") == 0)
130                        separator=1;
131                else if (strcmp(*argv,"-rand") == 0)
132                        {
133                        if (--argc < 1) break;
134                        randfile=*(++argv);
135                        }
136                else if (strcmp(*argv,"-out") == 0)
137                        {
138                        if (--argc < 1) break;
139                        outfile=*(++argv);
140                        }
141                else if (strcmp(*argv,"-sign") == 0)
142                        {
143                        if (--argc < 1) break;
144                        keyfile=*(++argv);
145                        }
146                else if (strcmp(*argv,"-verify") == 0)
147                        {
148                        if (--argc < 1) break;
149                        keyfile=*(++argv);
150                        want_pub = 1;
151                        do_verify = 1;
152                        }
153                else if (strcmp(*argv,"-prverify") == 0)
154                        {
155                        if (--argc < 1) break;
156                        keyfile=*(++argv);
157                        do_verify = 1;
158                        }
159                else if (strcmp(*argv,"-signature") == 0)
160                        {
161                        if (--argc < 1) break;
162                        sigfile=*(++argv);
163                        }
164                else if (strcmp(*argv,"-keyform") == 0)
165                        {
166                        if (--argc < 1) break;
167                        keyform=str2fmt(*(++argv));
168                        }
169                else if (strcmp(*argv,"-engine") == 0)
170                        {
171                        if (--argc < 1) break;
172                        engine= *(++argv);
173                        }
174                else if (strcmp(*argv,"-hex") == 0)
175                        out_bin = 0;
176                else if (strcmp(*argv,"-binary") == 0)
177                        out_bin = 1;
178                else if (strcmp(*argv,"-d") == 0)
179                        debug=1;
180                else if ((m=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
181                        md=m;
182                else
183                        break;
184                argc--;
185                argv++;
186                }
187
188        if (md == NULL)
189                md=EVP_md5();
190
191        if(do_verify && !sigfile) {
192                BIO_printf(bio_err, "No signature to verify: use the -signature option\n");
193                err = 1;
194                goto end;
195        }
196
197        if ((argc > 0) && (argv[0][0] == '-')) /* bad option */
198                {
199                BIO_printf(bio_err,"unknown option '%s'\n",*argv);
200                BIO_printf(bio_err,"options are\n");
201                BIO_printf(bio_err,"-c              to output the digest with separating colons\n");
202                BIO_printf(bio_err,"-d              to output debug info\n");
203                BIO_printf(bio_err,"-hex            output as hex dump\n");
204                BIO_printf(bio_err,"-binary         output in binary form\n");
205                BIO_printf(bio_err,"-sign   file    sign digest using private key in file\n");
206                BIO_printf(bio_err,"-verify file    verify a signature using public key in file\n");
207                BIO_printf(bio_err,"-prverify file  verify a signature using private key in file\n");
208                BIO_printf(bio_err,"-keyform arg    key file format (PEM or ENGINE)\n");
209                BIO_printf(bio_err,"-signature file signature to verify\n");
210                BIO_printf(bio_err,"-binary         output in binary form\n");
211                BIO_printf(bio_err,"-engine e       use engine e, possibly a hardware device.\n");
212
213                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm (default)\n",
214                        LN_md5,LN_md5);
215                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
216                        LN_md4,LN_md4);
217                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
218                        LN_md2,LN_md2);
219                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
220                        LN_sha1,LN_sha1);
221                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
222                        LN_sha,LN_sha);
223                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
224                        LN_mdc2,LN_mdc2);
225                BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n",
226                        LN_ripemd160,LN_ripemd160);
227                err=1;
228                goto end;
229                }
230
231        e = setup_engine(bio_err, engine, 0);
232
233        in=BIO_new(BIO_s_file());
234        bmd=BIO_new(BIO_f_md());
235        if (debug)
236                {
237                BIO_set_callback(in,BIO_debug_callback);
238                /* needed for windows 3.1 */
239                BIO_set_callback_arg(in,bio_err);
240                }
241
242        if ((in == NULL) || (bmd == NULL))
243                {
244                ERR_print_errors(bio_err);
245                goto end;
246                }
247
248        if(out_bin == -1) {
249                if(keyfile) out_bin = 1;
250                else out_bin = 0;
251        }
252
253        if(randfile)
254                app_RAND_load_file(randfile, bio_err, 0);
255
256        if(outfile) {
257                if(out_bin)
258                        out = BIO_new_file(outfile, "wb");
259                else    out = BIO_new_file(outfile, "w");
260        } else {
261                out = BIO_new_fp(stdout, BIO_NOCLOSE);
262#ifdef OPENSSL_SYS_VMS
263                {
264                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
265                out = BIO_push(tmpbio, out);
266                }
267#endif
268        }
269
270        if(!out) {
271                BIO_printf(bio_err, "Error opening output file %s\n",
272                                        outfile ? outfile : "(stdout)");
273                ERR_print_errors(bio_err);
274                goto end;
275        }
276
277        if(keyfile)
278                {
279                if (want_pub)
280                        sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL,
281                                e, "key file");
282                else
283                        sigkey = load_key(bio_err, keyfile, keyform, 0, NULL,
284                                e, "key file");
285                if (!sigkey)
286                        {
287                        /* load_[pub]key() has already printed an appropriate
288                           message */
289                        goto end;
290                        }
291                }
292
293        if(sigfile && sigkey) {
294                BIO *sigbio;
295                sigbio = BIO_new_file(sigfile, "rb");
296                siglen = EVP_PKEY_size(sigkey);
297                sigbuf = OPENSSL_malloc(siglen);
298                if(!sigbio) {
299                        BIO_printf(bio_err, "Error opening signature file %s\n",
300                                                                sigfile);
301                        ERR_print_errors(bio_err);
302                        goto end;
303                }
304                siglen = BIO_read(sigbio, sigbuf, siglen);
305                BIO_free(sigbio);
306                if(siglen <= 0) {
307                        BIO_printf(bio_err, "Error reading signature file %s\n",
308                                                                sigfile);
309                        ERR_print_errors(bio_err);
310                        goto end;
311                }
312        }
313               
314
315
316        /* we use md as a filter, reading from 'in' */
317        BIO_set_md(bmd,md);
318        inp=BIO_push(bmd,in);
319
320        if (argc == 0)
321                {
322                BIO_set_fp(in,stdin,BIO_NOCLOSE);
323                err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf,
324                          siglen,"","(stdin)");
325                }
326        else
327                {
328                name=OBJ_nid2sn(md->type);
329                for (i=0; i<argc; i++)
330                        {
331                        char *tmp,*tofree=NULL;
332                        int r;
333
334                        if (BIO_read_filename(in,argv[i]) <= 0)
335                                {
336                                perror(argv[i]);
337                                err++;
338                                continue;
339                                }
340                        if(!out_bin)
341                                {
342                                tmp=tofree=OPENSSL_malloc(strlen(name)+strlen(argv[i])+5);
343                                sprintf(tmp,"%s(%s)= ",name,argv[i]);
344                                }
345                        else
346                                tmp="";
347                        r=do_fp(out,buf,inp,separator,out_bin,sigkey,sigbuf,
348                                siglen,tmp,argv[i]);
349                        if(r)
350                            err=r;
351                        if(tofree)
352                                OPENSSL_free(tofree);
353                        (void)BIO_reset(bmd);
354                        }
355                }
356end:
357        if (buf != NULL)
358                {
359                OPENSSL_cleanse(buf,BUFSIZE);
360                OPENSSL_free(buf);
361                }
362        if (in != NULL) BIO_free(in);
363        BIO_free_all(out);
364        EVP_PKEY_free(sigkey);
365        if(sigbuf) OPENSSL_free(sigbuf);
366        if (bmd != NULL) BIO_free(bmd);
367        apps_shutdown();
368        OPENSSL_EXIT(err);
369        }
370
371int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
372          EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title,
373          const char *file)
374        {
375        int len;
376        int i;
377
378        for (;;)
379                {
380                i=BIO_read(bp,(char *)buf,BUFSIZE);
381                if(i < 0)
382                        {
383                        BIO_printf(bio_err, "Read Error in %s\n",file);
384                        ERR_print_errors(bio_err);
385                        return 1;
386                        }
387                if (i == 0) break;
388                }
389        if(sigin)
390                {
391                EVP_MD_CTX *ctx;
392                BIO_get_md_ctx(bp, &ctx);
393                i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key);
394                if(i > 0)
395                        BIO_printf(out, "Verified OK\n");
396                else if(i == 0)
397                        {
398                        BIO_printf(out, "Verification Failure\n");
399                        return 1;
400                        }
401                else
402                        {
403                        BIO_printf(bio_err, "Error Verifying Data\n");
404                        ERR_print_errors(bio_err);
405                        return 1;
406                        }
407                return 0;
408                }
409        if(key)
410                {
411                EVP_MD_CTX *ctx;
412                BIO_get_md_ctx(bp, &ctx);
413                if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key))
414                        {
415                        BIO_printf(bio_err, "Error Signing Data\n");
416                        ERR_print_errors(bio_err);
417                        return 1;
418                        }
419                }
420        else
421                len=BIO_gets(bp,(char *)buf,BUFSIZE);
422
423        if(binout) BIO_write(out, buf, len);
424        else
425                {
426                BIO_write(out,title,strlen(title));
427                for (i=0; i<len; i++)
428                        {
429                        if (sep && (i != 0))
430                                BIO_printf(out, ":");
431                        BIO_printf(out, "%02x",buf[i]);
432                        }
433                BIO_printf(out, "\n");
434                }
435        return 0;
436        }
437
Note: See TracBrowser for help on using the repository browser.