1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: dgst.c,v 1.19 2022/01/14 09:28:07 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino * All rights reserved.
4f5b1c8a1SJohn Marino *
5f5b1c8a1SJohn Marino * This package is an SSL implementation written
6f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino *
9f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions
11f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino *
16f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino * the code are not to be removed.
18f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino *
23f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino * are met:
26f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino * must display the following acknowledgement:
33f5b1c8a1SJohn Marino * "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino * being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino *
41f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino * SUCH DAMAGE.
52f5b1c8a1SJohn Marino *
53f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be
55f5b1c8a1SJohn Marino * copied and put under another distribution licence
56f5b1c8a1SJohn Marino * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino */
58f5b1c8a1SJohn Marino
59f5b1c8a1SJohn Marino #include <stdio.h>
60f5b1c8a1SJohn Marino #include <stdlib.h>
61f5b1c8a1SJohn Marino #include <string.h>
62f5b1c8a1SJohn Marino
63f5b1c8a1SJohn Marino #include "apps.h"
64f5b1c8a1SJohn Marino
65f5b1c8a1SJohn Marino #include <openssl/bio.h>
66f5b1c8a1SJohn Marino #include <openssl/err.h>
67f5b1c8a1SJohn Marino #include <openssl/evp.h>
68f5b1c8a1SJohn Marino #include <openssl/hmac.h>
69f5b1c8a1SJohn Marino #include <openssl/objects.h>
70f5b1c8a1SJohn Marino #include <openssl/pem.h>
71f5b1c8a1SJohn Marino #include <openssl/x509.h>
72f5b1c8a1SJohn Marino
73f5b1c8a1SJohn Marino #define BUFSIZE 1024*8
74f5b1c8a1SJohn Marino
75f5b1c8a1SJohn Marino int
76f5b1c8a1SJohn Marino do_fp(BIO * out, unsigned char *buf, BIO * bp, int sep, int binout,
77f5b1c8a1SJohn Marino EVP_PKEY * key, unsigned char *sigin, int siglen,
78f5b1c8a1SJohn Marino const char *sig_name, const char *md_name,
79f5b1c8a1SJohn Marino const char *file, BIO * bmd);
80f5b1c8a1SJohn Marino
81cca6fc52SDaniel Fojt static struct {
82cca6fc52SDaniel Fojt int argsused;
83cca6fc52SDaniel Fojt int debug;
84cca6fc52SDaniel Fojt int do_verify;
85cca6fc52SDaniel Fojt char *hmac_key;
86cca6fc52SDaniel Fojt char *keyfile;
87cca6fc52SDaniel Fojt int keyform;
88cca6fc52SDaniel Fojt const EVP_MD *m;
89cca6fc52SDaniel Fojt char *mac_name;
90cca6fc52SDaniel Fojt STACK_OF(OPENSSL_STRING) *macopts;
91cca6fc52SDaniel Fojt const EVP_MD *md;
92cca6fc52SDaniel Fojt int out_bin;
93cca6fc52SDaniel Fojt char *outfile;
94cca6fc52SDaniel Fojt char *passargin;
95cca6fc52SDaniel Fojt int separator;
96cca6fc52SDaniel Fojt char *sigfile;
97cca6fc52SDaniel Fojt STACK_OF(OPENSSL_STRING) *sigopts;
98cca6fc52SDaniel Fojt int want_pub;
99cca6fc52SDaniel Fojt } dgst_config;
100cca6fc52SDaniel Fojt
101cca6fc52SDaniel Fojt static int
dgst_opt_macopt(char * arg)102cca6fc52SDaniel Fojt dgst_opt_macopt(char *arg)
103cca6fc52SDaniel Fojt {
104cca6fc52SDaniel Fojt if (arg == NULL)
105cca6fc52SDaniel Fojt return (1);
106cca6fc52SDaniel Fojt
107cca6fc52SDaniel Fojt if (dgst_config.macopts == NULL &&
108cca6fc52SDaniel Fojt (dgst_config.macopts = sk_OPENSSL_STRING_new_null()) == NULL)
109cca6fc52SDaniel Fojt return (1);
110cca6fc52SDaniel Fojt
111cca6fc52SDaniel Fojt if (!sk_OPENSSL_STRING_push(dgst_config.macopts, arg))
112cca6fc52SDaniel Fojt return (1);
113cca6fc52SDaniel Fojt
114cca6fc52SDaniel Fojt return (0);
115cca6fc52SDaniel Fojt }
116cca6fc52SDaniel Fojt
117cca6fc52SDaniel Fojt static int
dgst_opt_md(int argc,char ** argv,int * argsused)118cca6fc52SDaniel Fojt dgst_opt_md(int argc, char **argv, int *argsused)
119cca6fc52SDaniel Fojt {
120cca6fc52SDaniel Fojt char *name = argv[0];
121cca6fc52SDaniel Fojt
122cca6fc52SDaniel Fojt if (*name++ != '-')
123cca6fc52SDaniel Fojt return (1);
124cca6fc52SDaniel Fojt
125cca6fc52SDaniel Fojt if ((dgst_config.m = EVP_get_digestbyname(name)) == NULL)
126cca6fc52SDaniel Fojt return (1);
127cca6fc52SDaniel Fojt
128cca6fc52SDaniel Fojt dgst_config.md = dgst_config.m;
129cca6fc52SDaniel Fojt
130cca6fc52SDaniel Fojt *argsused = 1;
131cca6fc52SDaniel Fojt return (0);
132cca6fc52SDaniel Fojt }
133cca6fc52SDaniel Fojt
134cca6fc52SDaniel Fojt static int
dgst_opt_prverify(char * arg)135cca6fc52SDaniel Fojt dgst_opt_prverify(char *arg)
136cca6fc52SDaniel Fojt {
137cca6fc52SDaniel Fojt if (arg == NULL)
138cca6fc52SDaniel Fojt return (1);
139cca6fc52SDaniel Fojt
140cca6fc52SDaniel Fojt dgst_config.keyfile = arg;
141cca6fc52SDaniel Fojt dgst_config.do_verify = 1;
142cca6fc52SDaniel Fojt return (0);
143cca6fc52SDaniel Fojt }
144cca6fc52SDaniel Fojt
145cca6fc52SDaniel Fojt static int
dgst_opt_sigopt(char * arg)146cca6fc52SDaniel Fojt dgst_opt_sigopt(char *arg)
147cca6fc52SDaniel Fojt {
148cca6fc52SDaniel Fojt if (arg == NULL)
149cca6fc52SDaniel Fojt return (1);
150cca6fc52SDaniel Fojt
151cca6fc52SDaniel Fojt if (dgst_config.sigopts == NULL &&
152cca6fc52SDaniel Fojt (dgst_config.sigopts = sk_OPENSSL_STRING_new_null()) == NULL)
153cca6fc52SDaniel Fojt return (1);
154cca6fc52SDaniel Fojt
155cca6fc52SDaniel Fojt if (!sk_OPENSSL_STRING_push(dgst_config.sigopts, arg))
156cca6fc52SDaniel Fojt return (1);
157cca6fc52SDaniel Fojt
158cca6fc52SDaniel Fojt return (0);
159cca6fc52SDaniel Fojt }
160cca6fc52SDaniel Fojt
161cca6fc52SDaniel Fojt static int
dgst_opt_verify(char * arg)162cca6fc52SDaniel Fojt dgst_opt_verify(char *arg)
163cca6fc52SDaniel Fojt {
164cca6fc52SDaniel Fojt if (arg == NULL)
165cca6fc52SDaniel Fojt return (1);
166cca6fc52SDaniel Fojt
167cca6fc52SDaniel Fojt dgst_config.keyfile = arg;
168cca6fc52SDaniel Fojt dgst_config.want_pub = 1;
169cca6fc52SDaniel Fojt dgst_config.do_verify = 1;
170cca6fc52SDaniel Fojt return (0);
171cca6fc52SDaniel Fojt }
172cca6fc52SDaniel Fojt
173cca6fc52SDaniel Fojt static const struct option dgst_options[] = {
174cca6fc52SDaniel Fojt {
175cca6fc52SDaniel Fojt .name = "binary",
176cca6fc52SDaniel Fojt .desc = "Output the digest or signature in binary form",
177cca6fc52SDaniel Fojt .type = OPTION_VALUE,
178cca6fc52SDaniel Fojt .opt.value = &dgst_config.out_bin,
179cca6fc52SDaniel Fojt .value = 1,
180cca6fc52SDaniel Fojt },
181cca6fc52SDaniel Fojt {
182cca6fc52SDaniel Fojt .name = "c",
183cca6fc52SDaniel Fojt .desc = "Print the digest in two-digit groups separated by colons",
184cca6fc52SDaniel Fojt .type = OPTION_VALUE,
185cca6fc52SDaniel Fojt .opt.value = &dgst_config.separator,
186cca6fc52SDaniel Fojt .value = 1,
187cca6fc52SDaniel Fojt },
188cca6fc52SDaniel Fojt {
189cca6fc52SDaniel Fojt .name = "d",
190cca6fc52SDaniel Fojt .desc = "Print BIO debugging information",
191cca6fc52SDaniel Fojt .type = OPTION_FLAG,
192cca6fc52SDaniel Fojt .opt.flag = &dgst_config.debug,
193cca6fc52SDaniel Fojt },
194cca6fc52SDaniel Fojt {
195cca6fc52SDaniel Fojt .name = "hex",
196cca6fc52SDaniel Fojt .desc = "Output as hex dump",
197cca6fc52SDaniel Fojt .type = OPTION_VALUE,
198cca6fc52SDaniel Fojt .opt.value = &dgst_config.out_bin,
199cca6fc52SDaniel Fojt .value = 0,
200cca6fc52SDaniel Fojt },
201cca6fc52SDaniel Fojt {
202cca6fc52SDaniel Fojt .name = "hmac",
203cca6fc52SDaniel Fojt .argname = "key",
204cca6fc52SDaniel Fojt .desc = "Create hashed MAC with key",
205cca6fc52SDaniel Fojt .type = OPTION_ARG,
206cca6fc52SDaniel Fojt .opt.arg = &dgst_config.hmac_key,
207cca6fc52SDaniel Fojt },
208cca6fc52SDaniel Fojt {
209cca6fc52SDaniel Fojt .name = "keyform",
210cca6fc52SDaniel Fojt .argname = "format",
211cca6fc52SDaniel Fojt .desc = "Key file format (PEM)",
212cca6fc52SDaniel Fojt .type = OPTION_ARG_FORMAT,
213cca6fc52SDaniel Fojt .opt.value = &dgst_config.keyform,
214cca6fc52SDaniel Fojt },
215cca6fc52SDaniel Fojt {
216cca6fc52SDaniel Fojt .name = "mac",
217cca6fc52SDaniel Fojt .argname = "algorithm",
218cca6fc52SDaniel Fojt .desc = "Create MAC (not necessarily HMAC)",
219cca6fc52SDaniel Fojt .type = OPTION_ARG,
220cca6fc52SDaniel Fojt .opt.arg = &dgst_config.mac_name,
221cca6fc52SDaniel Fojt },
222cca6fc52SDaniel Fojt {
223cca6fc52SDaniel Fojt .name = "macopt",
224cca6fc52SDaniel Fojt .argname = "nm:v",
225cca6fc52SDaniel Fojt .desc = "MAC algorithm parameters or key",
226cca6fc52SDaniel Fojt .type = OPTION_ARG_FUNC,
227cca6fc52SDaniel Fojt .opt.argfunc = dgst_opt_macopt,
228cca6fc52SDaniel Fojt },
229cca6fc52SDaniel Fojt {
230cca6fc52SDaniel Fojt .name = "out",
231cca6fc52SDaniel Fojt .argname = "file",
232cca6fc52SDaniel Fojt .desc = "Output to file rather than stdout",
233cca6fc52SDaniel Fojt .type = OPTION_ARG,
234cca6fc52SDaniel Fojt .opt.arg = &dgst_config.outfile,
235cca6fc52SDaniel Fojt },
236cca6fc52SDaniel Fojt {
237cca6fc52SDaniel Fojt .name = "passin",
238cca6fc52SDaniel Fojt .argname = "arg",
239cca6fc52SDaniel Fojt .desc = "Input file passphrase source",
240cca6fc52SDaniel Fojt .type = OPTION_ARG,
241cca6fc52SDaniel Fojt .opt.arg = &dgst_config.passargin,
242cca6fc52SDaniel Fojt },
243cca6fc52SDaniel Fojt {
244cca6fc52SDaniel Fojt .name = "prverify",
245cca6fc52SDaniel Fojt .argname = "file",
246cca6fc52SDaniel Fojt .desc = "Verify a signature using private key in file",
247cca6fc52SDaniel Fojt .type = OPTION_ARG_FUNC,
248cca6fc52SDaniel Fojt .opt.argfunc = dgst_opt_prverify,
249cca6fc52SDaniel Fojt },
250cca6fc52SDaniel Fojt {
251cca6fc52SDaniel Fojt .name = "r",
252cca6fc52SDaniel Fojt .desc = "Output the digest in coreutils format",
253cca6fc52SDaniel Fojt .type = OPTION_VALUE,
254cca6fc52SDaniel Fojt .opt.value = &dgst_config.separator,
255cca6fc52SDaniel Fojt .value = 2,
256cca6fc52SDaniel Fojt },
257cca6fc52SDaniel Fojt {
258cca6fc52SDaniel Fojt .name = "sign",
259cca6fc52SDaniel Fojt .argname = "file",
260cca6fc52SDaniel Fojt .desc = "Sign digest using private key in file",
261cca6fc52SDaniel Fojt .type = OPTION_ARG,
262cca6fc52SDaniel Fojt .opt.arg = &dgst_config.keyfile,
263cca6fc52SDaniel Fojt },
264cca6fc52SDaniel Fojt {
265cca6fc52SDaniel Fojt .name = "signature",
266cca6fc52SDaniel Fojt .argname = "file",
267cca6fc52SDaniel Fojt .desc = "Signature to verify",
268cca6fc52SDaniel Fojt .type = OPTION_ARG,
269cca6fc52SDaniel Fojt .opt.arg = &dgst_config.sigfile,
270cca6fc52SDaniel Fojt },
271cca6fc52SDaniel Fojt {
272cca6fc52SDaniel Fojt .name = "sigopt",
273cca6fc52SDaniel Fojt .argname = "nm:v",
274cca6fc52SDaniel Fojt .desc = "Signature parameter",
275cca6fc52SDaniel Fojt .type = OPTION_ARG_FUNC,
276cca6fc52SDaniel Fojt .opt.argfunc = dgst_opt_sigopt,
277cca6fc52SDaniel Fojt },
278cca6fc52SDaniel Fojt {
279cca6fc52SDaniel Fojt .name = "verify",
280cca6fc52SDaniel Fojt .argname = "file",
281cca6fc52SDaniel Fojt .desc = "Verify a signature using public key in file",
282cca6fc52SDaniel Fojt .type = OPTION_ARG_FUNC,
283cca6fc52SDaniel Fojt .opt.argfunc = dgst_opt_verify,
284cca6fc52SDaniel Fojt },
285cca6fc52SDaniel Fojt {
286cca6fc52SDaniel Fojt .name = NULL,
287cca6fc52SDaniel Fojt .desc = "",
288cca6fc52SDaniel Fojt .type = OPTION_ARGV_FUNC,
289cca6fc52SDaniel Fojt .opt.argvfunc = dgst_opt_md,
290cca6fc52SDaniel Fojt },
291cca6fc52SDaniel Fojt { NULL },
292cca6fc52SDaniel Fojt };
293cca6fc52SDaniel Fojt
294f5b1c8a1SJohn Marino static void
list_md_fn(const EVP_MD * m,const char * from,const char * to,void * arg)295f5b1c8a1SJohn Marino list_md_fn(const EVP_MD * m, const char *from, const char *to, void *arg)
296f5b1c8a1SJohn Marino {
297f5b1c8a1SJohn Marino const char *mname;
298f5b1c8a1SJohn Marino /* Skip aliases */
299f5b1c8a1SJohn Marino if (!m)
300f5b1c8a1SJohn Marino return;
301f5b1c8a1SJohn Marino mname = OBJ_nid2ln(EVP_MD_type(m));
302f5b1c8a1SJohn Marino /* Skip shortnames */
303f5b1c8a1SJohn Marino if (strcmp(from, mname))
304f5b1c8a1SJohn Marino return;
305f5b1c8a1SJohn Marino if (strchr(mname, ' '))
306f5b1c8a1SJohn Marino mname = EVP_MD_name(m);
307cca6fc52SDaniel Fojt BIO_printf(arg, " -%-17s To use the %s message digest algorithm\n",
308f5b1c8a1SJohn Marino mname, mname);
309f5b1c8a1SJohn Marino }
310f5b1c8a1SJohn Marino
311cca6fc52SDaniel Fojt static void
dgst_usage(void)312cca6fc52SDaniel Fojt dgst_usage(void)
313cca6fc52SDaniel Fojt {
314cca6fc52SDaniel Fojt fprintf(stderr, "usage: dgst [-cdr] [-binary] [-digest] [-hex]");
315cca6fc52SDaniel Fojt fprintf(stderr, " [-hmac key] [-keyform fmt]\n");
316cca6fc52SDaniel Fojt fprintf(stderr, " [-mac algorithm] [-macopt nm:v] [-out file]");
317cca6fc52SDaniel Fojt fprintf(stderr, " [-passin arg]\n");
318cca6fc52SDaniel Fojt fprintf(stderr, " [-prverify file] [-sign file]");
319cca6fc52SDaniel Fojt fprintf(stderr, " [-signature file]\n");
320cca6fc52SDaniel Fojt fprintf(stderr, " [-sigopt nm:v] [-verify file] [file ...]\n\n");
321cca6fc52SDaniel Fojt options_usage(dgst_options);
322cca6fc52SDaniel Fojt EVP_MD_do_all_sorted(list_md_fn, bio_err);
323cca6fc52SDaniel Fojt fprintf(stderr, "\n");
324cca6fc52SDaniel Fojt }
325cca6fc52SDaniel Fojt
326f5b1c8a1SJohn Marino int
dgst_main(int argc,char ** argv)327f5b1c8a1SJohn Marino dgst_main(int argc, char **argv)
328f5b1c8a1SJohn Marino {
329f5b1c8a1SJohn Marino unsigned char *buf = NULL;
330f5b1c8a1SJohn Marino int i, err = 1;
331f5b1c8a1SJohn Marino BIO *in = NULL, *inp;
332f5b1c8a1SJohn Marino BIO *bmd = NULL;
333f5b1c8a1SJohn Marino BIO *out = NULL;
334f5b1c8a1SJohn Marino #define PROG_NAME_SIZE 39
335f5b1c8a1SJohn Marino char pname[PROG_NAME_SIZE + 1];
336f5b1c8a1SJohn Marino EVP_PKEY *sigkey = NULL;
337f5b1c8a1SJohn Marino unsigned char *sigbuf = NULL;
338f5b1c8a1SJohn Marino int siglen = 0;
339cca6fc52SDaniel Fojt char *passin = NULL;
340f5b1c8a1SJohn Marino
341f5b1c8a1SJohn Marino if (single_execution) {
34272c33676SMaxim Ag if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
343f5b1c8a1SJohn Marino perror("pledge");
344f5b1c8a1SJohn Marino exit(1);
345f5b1c8a1SJohn Marino }
346f5b1c8a1SJohn Marino }
347f5b1c8a1SJohn Marino
348f5b1c8a1SJohn Marino if ((buf = malloc(BUFSIZE)) == NULL) {
349f5b1c8a1SJohn Marino BIO_printf(bio_err, "out of memory\n");
350f5b1c8a1SJohn Marino goto end;
351f5b1c8a1SJohn Marino }
352f5b1c8a1SJohn Marino
353cca6fc52SDaniel Fojt memset(&dgst_config, 0, sizeof(dgst_config));
354cca6fc52SDaniel Fojt dgst_config.keyform = FORMAT_PEM;
355cca6fc52SDaniel Fojt dgst_config.out_bin = -1;
356cca6fc52SDaniel Fojt
357f5b1c8a1SJohn Marino /* first check the program name */
358f5b1c8a1SJohn Marino program_name(argv[0], pname, sizeof pname);
359f5b1c8a1SJohn Marino
360cca6fc52SDaniel Fojt dgst_config.md = EVP_get_digestbyname(pname);
361f5b1c8a1SJohn Marino
362cca6fc52SDaniel Fojt if (options_parse(argc, argv, dgst_options, NULL,
363cca6fc52SDaniel Fojt &dgst_config.argsused) != 0) {
364cca6fc52SDaniel Fojt dgst_usage();
365f5b1c8a1SJohn Marino goto end;
366f5b1c8a1SJohn Marino }
367cca6fc52SDaniel Fojt argc -= dgst_config.argsused;
368cca6fc52SDaniel Fojt argv += dgst_config.argsused;
369f5b1c8a1SJohn Marino
370cca6fc52SDaniel Fojt if (dgst_config.do_verify && !dgst_config.sigfile) {
371cca6fc52SDaniel Fojt BIO_printf(bio_err,
372cca6fc52SDaniel Fojt "No signature to verify: use the -signature option\n");
373f5b1c8a1SJohn Marino goto end;
374f5b1c8a1SJohn Marino }
375f5b1c8a1SJohn Marino
376f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file());
377f5b1c8a1SJohn Marino bmd = BIO_new(BIO_f_md());
378f5b1c8a1SJohn Marino if (in == NULL || bmd == NULL) {
379f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
380f5b1c8a1SJohn Marino goto end;
381f5b1c8a1SJohn Marino }
382f5b1c8a1SJohn Marino
383cca6fc52SDaniel Fojt if (dgst_config.debug) {
384f5b1c8a1SJohn Marino BIO_set_callback(in, BIO_debug_callback);
385f5b1c8a1SJohn Marino /* needed for windows 3.1 */
386f5b1c8a1SJohn Marino BIO_set_callback_arg(in, (char *) bio_err);
387f5b1c8a1SJohn Marino }
388cca6fc52SDaniel Fojt if (!app_passwd(bio_err, dgst_config.passargin, NULL, &passin, NULL)) {
389f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error getting password\n");
390f5b1c8a1SJohn Marino goto end;
391f5b1c8a1SJohn Marino }
392cca6fc52SDaniel Fojt if (dgst_config.out_bin == -1) {
393cca6fc52SDaniel Fojt if (dgst_config.keyfile)
394cca6fc52SDaniel Fojt dgst_config.out_bin = 1;
395f5b1c8a1SJohn Marino else
396cca6fc52SDaniel Fojt dgst_config.out_bin = 0;
397f5b1c8a1SJohn Marino }
398f5b1c8a1SJohn Marino
399cca6fc52SDaniel Fojt if (dgst_config.outfile) {
400cca6fc52SDaniel Fojt if (dgst_config.out_bin)
401cca6fc52SDaniel Fojt out = BIO_new_file(dgst_config.outfile, "wb");
402f5b1c8a1SJohn Marino else
403cca6fc52SDaniel Fojt out = BIO_new_file(dgst_config.outfile, "w");
404f5b1c8a1SJohn Marino } else {
405f5b1c8a1SJohn Marino out = BIO_new_fp(stdout, BIO_NOCLOSE);
406f5b1c8a1SJohn Marino }
407f5b1c8a1SJohn Marino
408f5b1c8a1SJohn Marino if (!out) {
409f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error opening output file %s\n",
410cca6fc52SDaniel Fojt dgst_config.outfile ? dgst_config.outfile : "(stdout)");
411f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
412f5b1c8a1SJohn Marino goto end;
413f5b1c8a1SJohn Marino }
414cca6fc52SDaniel Fojt if ((!!dgst_config.mac_name + !!dgst_config.keyfile +
415cca6fc52SDaniel Fojt !!dgst_config.hmac_key) > 1) {
416cca6fc52SDaniel Fojt BIO_printf(bio_err,
417cca6fc52SDaniel Fojt "MAC and Signing key cannot both be specified\n");
418f5b1c8a1SJohn Marino goto end;
419f5b1c8a1SJohn Marino }
420cca6fc52SDaniel Fojt if (dgst_config.keyfile) {
421cca6fc52SDaniel Fojt if (dgst_config.want_pub)
422cca6fc52SDaniel Fojt sigkey = load_pubkey(bio_err, dgst_config.keyfile,
423cca6fc52SDaniel Fojt dgst_config.keyform, 0, NULL, "key file");
424f5b1c8a1SJohn Marino else
425cca6fc52SDaniel Fojt sigkey = load_key(bio_err, dgst_config.keyfile,
426cca6fc52SDaniel Fojt dgst_config.keyform, 0, passin, "key file");
427f5b1c8a1SJohn Marino if (!sigkey) {
428f5b1c8a1SJohn Marino /*
429f5b1c8a1SJohn Marino * load_[pub]key() has already printed an appropriate
430f5b1c8a1SJohn Marino * message
431f5b1c8a1SJohn Marino */
432f5b1c8a1SJohn Marino goto end;
433f5b1c8a1SJohn Marino }
434f5b1c8a1SJohn Marino }
435cca6fc52SDaniel Fojt if (dgst_config.mac_name) {
436f5b1c8a1SJohn Marino EVP_PKEY_CTX *mac_ctx = NULL;
437f5b1c8a1SJohn Marino int r = 0;
438cca6fc52SDaniel Fojt if (!init_gen_str(bio_err, &mac_ctx, dgst_config.mac_name, 0))
439f5b1c8a1SJohn Marino goto mac_end;
440cca6fc52SDaniel Fojt if (dgst_config.macopts) {
441f5b1c8a1SJohn Marino char *macopt;
442cca6fc52SDaniel Fojt for (i = 0; i < sk_OPENSSL_STRING_num(
443cca6fc52SDaniel Fojt dgst_config.macopts); i++) {
444cca6fc52SDaniel Fojt macopt = sk_OPENSSL_STRING_value(
445cca6fc52SDaniel Fojt dgst_config.macopts, i);
446f5b1c8a1SJohn Marino if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
447f5b1c8a1SJohn Marino BIO_printf(bio_err,
448f5b1c8a1SJohn Marino "MAC parameter error \"%s\"\n",
449f5b1c8a1SJohn Marino macopt);
450f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
451f5b1c8a1SJohn Marino goto mac_end;
452f5b1c8a1SJohn Marino }
453f5b1c8a1SJohn Marino }
454f5b1c8a1SJohn Marino }
455f5b1c8a1SJohn Marino if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
456f5b1c8a1SJohn Marino BIO_puts(bio_err, "Error generating key\n");
457f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
458f5b1c8a1SJohn Marino goto mac_end;
459f5b1c8a1SJohn Marino }
460f5b1c8a1SJohn Marino r = 1;
461f5b1c8a1SJohn Marino mac_end:
462f5b1c8a1SJohn Marino EVP_PKEY_CTX_free(mac_ctx);
463f5b1c8a1SJohn Marino if (r == 0)
464f5b1c8a1SJohn Marino goto end;
465f5b1c8a1SJohn Marino }
466cca6fc52SDaniel Fojt if (dgst_config.hmac_key) {
467f5b1c8a1SJohn Marino sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
468cca6fc52SDaniel Fojt (unsigned char *) dgst_config.hmac_key, -1);
469f5b1c8a1SJohn Marino if (!sigkey)
470f5b1c8a1SJohn Marino goto end;
471f5b1c8a1SJohn Marino }
472f5b1c8a1SJohn Marino if (sigkey) {
473f5b1c8a1SJohn Marino EVP_MD_CTX *mctx = NULL;
474f5b1c8a1SJohn Marino EVP_PKEY_CTX *pctx = NULL;
475f5b1c8a1SJohn Marino int r;
476f5b1c8a1SJohn Marino if (!BIO_get_md_ctx(bmd, &mctx)) {
477f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error getting context\n");
478f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
479f5b1c8a1SJohn Marino goto end;
480f5b1c8a1SJohn Marino }
481cca6fc52SDaniel Fojt if (dgst_config.do_verify)
482cca6fc52SDaniel Fojt r = EVP_DigestVerifyInit(mctx, &pctx, dgst_config.md,
483cca6fc52SDaniel Fojt NULL, sigkey);
484f5b1c8a1SJohn Marino else
485cca6fc52SDaniel Fojt r = EVP_DigestSignInit(mctx, &pctx, dgst_config.md,
486cca6fc52SDaniel Fojt NULL, sigkey);
487f5b1c8a1SJohn Marino if (!r) {
488f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error setting context\n");
489f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
490f5b1c8a1SJohn Marino goto end;
491f5b1c8a1SJohn Marino }
492cca6fc52SDaniel Fojt if (dgst_config.sigopts) {
493f5b1c8a1SJohn Marino char *sigopt;
494cca6fc52SDaniel Fojt for (i = 0; i < sk_OPENSSL_STRING_num(
495cca6fc52SDaniel Fojt dgst_config.sigopts); i++) {
496cca6fc52SDaniel Fojt sigopt = sk_OPENSSL_STRING_value(
497cca6fc52SDaniel Fojt dgst_config.sigopts, i);
498f5b1c8a1SJohn Marino if (pkey_ctrl_string(pctx, sigopt) <= 0) {
499f5b1c8a1SJohn Marino BIO_printf(bio_err,
500f5b1c8a1SJohn Marino "parameter error \"%s\"\n",
501f5b1c8a1SJohn Marino sigopt);
502f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
503f5b1c8a1SJohn Marino goto end;
504f5b1c8a1SJohn Marino }
505f5b1c8a1SJohn Marino }
506f5b1c8a1SJohn Marino }
507f5b1c8a1SJohn Marino }
508f5b1c8a1SJohn Marino /* we use md as a filter, reading from 'in' */
509f5b1c8a1SJohn Marino else {
510cca6fc52SDaniel Fojt if (dgst_config.md == NULL)
511cca6fc52SDaniel Fojt dgst_config.md = EVP_sha256();
512cca6fc52SDaniel Fojt if (!BIO_set_md(bmd, dgst_config.md)) {
513f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error setting digest %s\n", pname);
514f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
515f5b1c8a1SJohn Marino goto end;
516f5b1c8a1SJohn Marino }
517f5b1c8a1SJohn Marino }
518f5b1c8a1SJohn Marino
519cca6fc52SDaniel Fojt if (dgst_config.sigfile && sigkey) {
520f5b1c8a1SJohn Marino BIO *sigbio;
521f5b1c8a1SJohn Marino siglen = EVP_PKEY_size(sigkey);
522f5b1c8a1SJohn Marino sigbuf = malloc(siglen);
523f5b1c8a1SJohn Marino if (sigbuf == NULL) {
524f5b1c8a1SJohn Marino BIO_printf(bio_err, "out of memory\n");
525f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
526f5b1c8a1SJohn Marino goto end;
527f5b1c8a1SJohn Marino }
528cca6fc52SDaniel Fojt sigbio = BIO_new_file(dgst_config.sigfile, "rb");
529f5b1c8a1SJohn Marino if (!sigbio) {
530f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error opening signature file %s\n",
531cca6fc52SDaniel Fojt dgst_config.sigfile);
532f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
533f5b1c8a1SJohn Marino goto end;
534f5b1c8a1SJohn Marino }
535f5b1c8a1SJohn Marino siglen = BIO_read(sigbio, sigbuf, siglen);
536f5b1c8a1SJohn Marino BIO_free(sigbio);
537f5b1c8a1SJohn Marino if (siglen <= 0) {
538f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error reading signature file %s\n",
539cca6fc52SDaniel Fojt dgst_config.sigfile);
540f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
541f5b1c8a1SJohn Marino goto end;
542f5b1c8a1SJohn Marino }
543f5b1c8a1SJohn Marino }
544f5b1c8a1SJohn Marino inp = BIO_push(bmd, in);
545f5b1c8a1SJohn Marino
546cca6fc52SDaniel Fojt if (dgst_config.md == NULL) {
547f5b1c8a1SJohn Marino EVP_MD_CTX *tctx;
548f5b1c8a1SJohn Marino BIO_get_md_ctx(bmd, &tctx);
549cca6fc52SDaniel Fojt dgst_config.md = EVP_MD_CTX_md(tctx);
550f5b1c8a1SJohn Marino }
551f5b1c8a1SJohn Marino if (argc == 0) {
552f5b1c8a1SJohn Marino BIO_set_fp(in, stdin, BIO_NOCLOSE);
553cca6fc52SDaniel Fojt err = do_fp(out, buf, inp, dgst_config.separator,
554cca6fc52SDaniel Fojt dgst_config.out_bin, sigkey, sigbuf, siglen, NULL, NULL,
555cca6fc52SDaniel Fojt "stdin", bmd);
556f5b1c8a1SJohn Marino } else {
557f5b1c8a1SJohn Marino const char *md_name = NULL, *sig_name = NULL;
558cca6fc52SDaniel Fojt if (!dgst_config.out_bin) {
559f5b1c8a1SJohn Marino if (sigkey) {
560f5b1c8a1SJohn Marino const EVP_PKEY_ASN1_METHOD *ameth;
561f5b1c8a1SJohn Marino ameth = EVP_PKEY_get0_asn1(sigkey);
562f5b1c8a1SJohn Marino if (ameth)
563f5b1c8a1SJohn Marino EVP_PKEY_asn1_get0_info(NULL, NULL,
564f5b1c8a1SJohn Marino NULL, NULL, &sig_name, ameth);
565f5b1c8a1SJohn Marino }
566cca6fc52SDaniel Fojt md_name = EVP_MD_name(dgst_config.md);
567f5b1c8a1SJohn Marino }
568f5b1c8a1SJohn Marino err = 0;
569f5b1c8a1SJohn Marino for (i = 0; i < argc; i++) {
570f5b1c8a1SJohn Marino int r;
571f5b1c8a1SJohn Marino if (BIO_read_filename(in, argv[i]) <= 0) {
572f5b1c8a1SJohn Marino perror(argv[i]);
573f5b1c8a1SJohn Marino err++;
574f5b1c8a1SJohn Marino continue;
575f5b1c8a1SJohn Marino } else {
576cca6fc52SDaniel Fojt r = do_fp(out, buf, inp, dgst_config.separator,
577cca6fc52SDaniel Fojt dgst_config.out_bin, sigkey, sigbuf, siglen,
578cca6fc52SDaniel Fojt sig_name, md_name, argv[i], bmd);
579f5b1c8a1SJohn Marino }
580f5b1c8a1SJohn Marino if (r)
581f5b1c8a1SJohn Marino err = r;
582f5b1c8a1SJohn Marino (void) BIO_reset(bmd);
583f5b1c8a1SJohn Marino }
584f5b1c8a1SJohn Marino }
585f5b1c8a1SJohn Marino
586f5b1c8a1SJohn Marino end:
58772c33676SMaxim Ag freezero(buf, BUFSIZE);
588f5b1c8a1SJohn Marino BIO_free(in);
589f5b1c8a1SJohn Marino free(passin);
590f5b1c8a1SJohn Marino BIO_free_all(out);
591f5b1c8a1SJohn Marino EVP_PKEY_free(sigkey);
592cca6fc52SDaniel Fojt sk_OPENSSL_STRING_free(dgst_config.sigopts);
593cca6fc52SDaniel Fojt sk_OPENSSL_STRING_free(dgst_config.macopts);
594f5b1c8a1SJohn Marino free(sigbuf);
595f5b1c8a1SJohn Marino BIO_free(bmd);
596f5b1c8a1SJohn Marino
597f5b1c8a1SJohn Marino return (err);
598f5b1c8a1SJohn Marino }
599f5b1c8a1SJohn Marino
600f5b1c8a1SJohn Marino int
do_fp(BIO * out,unsigned char * buf,BIO * bp,int sep,int binout,EVP_PKEY * key,unsigned char * sigin,int siglen,const char * sig_name,const char * md_name,const char * file,BIO * bmd)601f5b1c8a1SJohn Marino do_fp(BIO * out, unsigned char *buf, BIO * bp, int sep, int binout,
602f5b1c8a1SJohn Marino EVP_PKEY * key, unsigned char *sigin, int siglen,
603f5b1c8a1SJohn Marino const char *sig_name, const char *md_name,
604f5b1c8a1SJohn Marino const char *file, BIO * bmd)
605f5b1c8a1SJohn Marino {
606f5b1c8a1SJohn Marino size_t len;
607f5b1c8a1SJohn Marino int i;
608f5b1c8a1SJohn Marino
609f5b1c8a1SJohn Marino for (;;) {
610f5b1c8a1SJohn Marino i = BIO_read(bp, (char *) buf, BUFSIZE);
611f5b1c8a1SJohn Marino if (i < 0) {
612f5b1c8a1SJohn Marino BIO_printf(bio_err, "Read Error in %s\n", file);
613f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
614f5b1c8a1SJohn Marino return 1;
615f5b1c8a1SJohn Marino }
616f5b1c8a1SJohn Marino if (i == 0)
617f5b1c8a1SJohn Marino break;
618f5b1c8a1SJohn Marino }
619f5b1c8a1SJohn Marino if (sigin) {
620f5b1c8a1SJohn Marino EVP_MD_CTX *ctx;
621f5b1c8a1SJohn Marino BIO_get_md_ctx(bp, &ctx);
622f5b1c8a1SJohn Marino i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int) siglen);
623f5b1c8a1SJohn Marino if (i > 0)
624f5b1c8a1SJohn Marino BIO_printf(out, "Verified OK\n");
625f5b1c8a1SJohn Marino else if (i == 0) {
626f5b1c8a1SJohn Marino BIO_printf(out, "Verification Failure\n");
627f5b1c8a1SJohn Marino return 1;
628f5b1c8a1SJohn Marino } else {
629f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error Verifying Data\n");
630f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
631f5b1c8a1SJohn Marino return 1;
632f5b1c8a1SJohn Marino }
633f5b1c8a1SJohn Marino return 0;
634f5b1c8a1SJohn Marino }
635f5b1c8a1SJohn Marino if (key) {
636f5b1c8a1SJohn Marino EVP_MD_CTX *ctx;
637f5b1c8a1SJohn Marino BIO_get_md_ctx(bp, &ctx);
638f5b1c8a1SJohn Marino len = BUFSIZE;
639f5b1c8a1SJohn Marino if (!EVP_DigestSignFinal(ctx, buf, &len)) {
640f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error Signing Data\n");
641f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
642f5b1c8a1SJohn Marino return 1;
643f5b1c8a1SJohn Marino }
644f5b1c8a1SJohn Marino } else {
645f5b1c8a1SJohn Marino len = BIO_gets(bp, (char *) buf, BUFSIZE);
646f5b1c8a1SJohn Marino if ((int) len < 0) {
647f5b1c8a1SJohn Marino ERR_print_errors(bio_err);
648f5b1c8a1SJohn Marino return 1;
649f5b1c8a1SJohn Marino }
650f5b1c8a1SJohn Marino }
651f5b1c8a1SJohn Marino
652f5b1c8a1SJohn Marino if (binout)
653f5b1c8a1SJohn Marino BIO_write(out, buf, len);
654f5b1c8a1SJohn Marino else if (sep == 2) {
655f5b1c8a1SJohn Marino for (i = 0; i < (int) len; i++)
656f5b1c8a1SJohn Marino BIO_printf(out, "%02x", buf[i]);
657f5b1c8a1SJohn Marino BIO_printf(out, " *%s\n", file);
658f5b1c8a1SJohn Marino } else {
659f5b1c8a1SJohn Marino if (sig_name)
660f5b1c8a1SJohn Marino BIO_printf(out, "%s-%s(%s)= ", sig_name, md_name, file);
661f5b1c8a1SJohn Marino else if (md_name)
662f5b1c8a1SJohn Marino BIO_printf(out, "%s(%s)= ", md_name, file);
663f5b1c8a1SJohn Marino else
664f5b1c8a1SJohn Marino BIO_printf(out, "(%s)= ", file);
665f5b1c8a1SJohn Marino for (i = 0; i < (int) len; i++) {
666f5b1c8a1SJohn Marino if (sep && (i != 0))
667f5b1c8a1SJohn Marino BIO_printf(out, ":");
668f5b1c8a1SJohn Marino BIO_printf(out, "%02x", buf[i]);
669f5b1c8a1SJohn Marino }
670f5b1c8a1SJohn Marino BIO_printf(out, "\n");
671f5b1c8a1SJohn Marino }
672f5b1c8a1SJohn Marino return 0;
673f5b1c8a1SJohn Marino }
674