xref: /netbsd-src/crypto/external/bsd/openssl/dist/apps/dgst.c (revision 97e3c58506797315d86c0608cba9d3f55de0c735)
1c7da899bSchristos /*
2*97e3c585Schristos  * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
3a89c9211Schristos  *
4b0d17251Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
5c7da899bSchristos  * this file except in compliance with the License.  You can obtain a copy
6c7da899bSchristos  * in the file LICENSE in the source distribution or at
7c7da899bSchristos  * https://www.openssl.org/source/license.html
8a89c9211Schristos  */
9a89c9211Schristos 
10a89c9211Schristos #include <stdio.h>
11a89c9211Schristos #include <string.h>
12a89c9211Schristos #include <stdlib.h>
13a89c9211Schristos #include "apps.h"
1413d40330Schristos #include "progs.h"
15a89c9211Schristos #include <openssl/bio.h>
16a89c9211Schristos #include <openssl/err.h>
17a89c9211Schristos #include <openssl/evp.h>
18a89c9211Schristos #include <openssl/objects.h>
19a89c9211Schristos #include <openssl/x509.h>
20a89c9211Schristos #include <openssl/pem.h>
21a89c9211Schristos #include <openssl/hmac.h>
227d004720Schristos #include <ctype.h>
23a89c9211Schristos 
24a89c9211Schristos #undef BUFSIZE
25a89c9211Schristos #define BUFSIZE 1024*8
26a89c9211Schristos 
27b0d17251Schristos int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
28a89c9211Schristos           EVP_PKEY *key, unsigned char *sigin, int siglen,
29a89c9211Schristos           const char *sig_name, const char *md_name,
30c7da899bSchristos           const char *file);
317d004720Schristos static void show_digests(const OBJ_NAME *name, void *bio_);
327d004720Schristos 
337d004720Schristos struct doall_dgst_digests {
347d004720Schristos     BIO *bio;
357d004720Schristos     int n;
367d004720Schristos };
37a89c9211Schristos 
38c7da899bSchristos typedef enum OPTION_choice {
39b0d17251Schristos     OPT_COMMON,
40b0d17251Schristos     OPT_LIST,
4113d40330Schristos     OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
42c7da899bSchristos     OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
43c7da899bSchristos     OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
44b0d17251Schristos     OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN,
4513d40330Schristos     OPT_DIGEST,
46b0d17251Schristos     OPT_R_ENUM, OPT_PROV_ENUM
47c7da899bSchristos } OPTION_CHOICE;
48a89c9211Schristos 
4913d40330Schristos const OPTIONS dgst_options[] = {
50c7da899bSchristos     {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"},
51b0d17251Schristos 
52b0d17251Schristos     OPT_SECTION("General"),
53c7da899bSchristos     {"help", OPT_HELP, '-', "Display this summary"},
547d004720Schristos     {"list", OPT_LIST, '-', "List digests"},
55a89c9211Schristos #ifndef OPENSSL_NO_ENGINE
56c7da899bSchristos     {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
57c7da899bSchristos     {"engine_impl", OPT_ENGINE_IMPL, '-',
58c7da899bSchristos      "Also use engine given by -engine for digest operations"},
59a89c9211Schristos #endif
60b0d17251Schristos     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
61b0d17251Schristos 
62b0d17251Schristos     OPT_SECTION("Output"),
63b0d17251Schristos     {"c", OPT_C, '-', "Print the digest with separating colons"},
64b0d17251Schristos     {"r", OPT_R, '-', "Print the digest in coreutils format"},
65b0d17251Schristos     {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
66b0d17251Schristos     {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
67b0d17251Schristos     {"hex", OPT_HEX, '-', "Print as hex dump"},
68b0d17251Schristos     {"binary", OPT_BINARY, '-', "Print in binary form"},
69b0d17251Schristos     {"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256"},
70b0d17251Schristos     {"d", OPT_DEBUG, '-', "Print debug info"},
71b0d17251Schristos     {"debug", OPT_DEBUG, '-', "Print debug info"},
72b0d17251Schristos 
73b0d17251Schristos     OPT_SECTION("Signing"),
74b0d17251Schristos     {"sign", OPT_SIGN, 's', "Sign digest using private key"},
75b0d17251Schristos     {"verify", OPT_VERIFY, 's', "Verify a signature using public key"},
76b0d17251Schristos     {"prverify", OPT_PRVERIFY, 's', "Verify a signature using private key"},
77b0d17251Schristos     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
78b0d17251Schristos     {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
79b0d17251Schristos     {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
80b0d17251Schristos     {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
81b0d17251Schristos     {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
82b0d17251Schristos     {"", OPT_DIGEST, '-', "Any supported digest"},
83b0d17251Schristos     {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
84b0d17251Schristos      "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
85b0d17251Schristos 
86b0d17251Schristos     OPT_R_OPTIONS,
87b0d17251Schristos     OPT_PROV_OPTIONS,
88b0d17251Schristos 
89b0d17251Schristos     OPT_PARAMETERS(),
90b0d17251Schristos     {"file", 0, 0, "Files to digest (optional; default is stdin)"},
91c7da899bSchristos     {NULL}
92c7da899bSchristos };
93c7da899bSchristos 
94c7da899bSchristos int dgst_main(int argc, char **argv)
95c7da899bSchristos {
96c7da899bSchristos     BIO *in = NULL, *inp, *bmd = NULL, *out = NULL;
97c7da899bSchristos     ENGINE *e = NULL, *impl = NULL;
98c7da899bSchristos     EVP_PKEY *sigkey = NULL;
99c7da899bSchristos     STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
100a89c9211Schristos     char *hmac_key = NULL;
101b0d17251Schristos     char *mac_name = NULL, *digestname = NULL;
102c7da899bSchristos     char *passinarg = NULL, *passin = NULL;
103b0d17251Schristos     EVP_MD *md = NULL;
104c7da899bSchristos     const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
10513d40330Schristos     const char *sigfile = NULL;
106b0d17251Schristos     const char *md_name = NULL;
107c7da899bSchristos     OPTION_CHOICE o;
108b0d17251Schristos     int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0;
109b0d17251Schristos     int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0;
110b0d17251Schristos     int xoflen = 0;
111c7da899bSchristos     unsigned char *buf = NULL, *sigbuf = NULL;
112c7da899bSchristos     int engine_impl = 0;
1137d004720Schristos     struct doall_dgst_digests dec;
114a89c9211Schristos 
115c7da899bSchristos     buf = app_malloc(BUFSIZE, "I/O buffer");
116b0d17251Schristos     md = (EVP_MD *)EVP_get_digestbyname(argv[0]);
117b0d17251Schristos     if (md != NULL)
118b0d17251Schristos         digestname = argv[0];
119a89c9211Schristos 
120c7da899bSchristos     prog = opt_init(argc, argv, dgst_options);
121c7da899bSchristos     while ((o = opt_next()) != OPT_EOF) {
122c7da899bSchristos         switch (o) {
123c7da899bSchristos         case OPT_EOF:
124c7da899bSchristos         case OPT_ERR:
125c7da899bSchristos  opthelp:
126c7da899bSchristos             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
127a89c9211Schristos             goto end;
128c7da899bSchristos         case OPT_HELP:
129c7da899bSchristos             opt_help(dgst_options);
130b0d17251Schristos             ret = EXIT_SUCCESS;
131a89c9211Schristos             goto end;
1327d004720Schristos         case OPT_LIST:
1337d004720Schristos             BIO_printf(bio_out, "Supported digests:\n");
1347d004720Schristos             dec.bio = bio_out;
1357d004720Schristos             dec.n = 0;
1367d004720Schristos             OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
1377d004720Schristos                                    show_digests, &dec);
1387d004720Schristos             BIO_printf(bio_out, "\n");
139b0d17251Schristos             ret = EXIT_SUCCESS;
1407d004720Schristos             goto end;
141c7da899bSchristos         case OPT_C:
142a89c9211Schristos             separator = 1;
143c7da899bSchristos             break;
144c7da899bSchristos         case OPT_R:
145cef2ee70Schristos             separator = 2;
146635165faSspz             break;
14713d40330Schristos         case OPT_R_CASES:
14813d40330Schristos             if (!opt_rand(o))
14913d40330Schristos                 goto end;
150635165faSspz             break;
151c7da899bSchristos         case OPT_OUT:
152c7da899bSchristos             outfile = opt_arg();
153635165faSspz             break;
154c7da899bSchristos         case OPT_SIGN:
155c7da899bSchristos             keyfile = opt_arg();
156a89c9211Schristos             break;
157c7da899bSchristos         case OPT_PASSIN:
158c7da899bSchristos             passinarg = opt_arg();
159635165faSspz             break;
160c7da899bSchristos         case OPT_VERIFY:
161c7da899bSchristos             keyfile = opt_arg();
162c7da899bSchristos             want_pub = do_verify = 1;
163c7da899bSchristos             break;
164c7da899bSchristos         case OPT_PRVERIFY:
165c7da899bSchristos             keyfile = opt_arg();
166a89c9211Schristos             do_verify = 1;
167635165faSspz             break;
168c7da899bSchristos         case OPT_SIGNATURE:
169c7da899bSchristos             sigfile = opt_arg();
170635165faSspz             break;
171c7da899bSchristos         case OPT_KEYFORM:
172c7da899bSchristos             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
173c7da899bSchristos                 goto opthelp;
174635165faSspz             break;
175c7da899bSchristos         case OPT_ENGINE:
176c7da899bSchristos             e = setup_engine(opt_arg(), 0);
177635165faSspz             break;
178c7da899bSchristos         case OPT_ENGINE_IMPL:
179218f7bfcSspz             engine_impl = 1;
180c7da899bSchristos             break;
181c7da899bSchristos         case OPT_HEX:
182a89c9211Schristos             out_bin = 0;
183c7da899bSchristos             break;
184c7da899bSchristos         case OPT_BINARY:
185a89c9211Schristos             out_bin = 1;
186c7da899bSchristos             break;
187b0d17251Schristos         case OPT_XOFLEN:
188b0d17251Schristos             xoflen = atoi(opt_arg());
189b0d17251Schristos             break;
190c7da899bSchristos         case OPT_DEBUG:
191a89c9211Schristos             debug = 1;
192c7da899bSchristos             break;
193c7da899bSchristos         case OPT_FIPS_FINGERPRINT:
19432daad53Schristos             hmac_key = "etaonrishdlcupfm";
195a89c9211Schristos             break;
196c7da899bSchristos         case OPT_HMAC:
197c7da899bSchristos             hmac_key = opt_arg();
198a89c9211Schristos             break;
199c7da899bSchristos         case OPT_MAC:
200c7da899bSchristos             mac_name = opt_arg();
201a89c9211Schristos             break;
202c7da899bSchristos         case OPT_SIGOPT:
203a89c9211Schristos             if (!sigopts)
20486adef1bSchristos                 sigopts = sk_OPENSSL_STRING_new_null();
205c7da899bSchristos             if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
206c7da899bSchristos                 goto opthelp;
207a89c9211Schristos             break;
208c7da899bSchristos         case OPT_MACOPT:
209a89c9211Schristos             if (!macopts)
21086adef1bSchristos                 macopts = sk_OPENSSL_STRING_new_null();
211c7da899bSchristos             if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg()))
212c7da899bSchristos                 goto opthelp;
213a89c9211Schristos             break;
214c7da899bSchristos         case OPT_DIGEST:
215b0d17251Schristos             digestname = opt_unknown();
216b0d17251Schristos             break;
217b0d17251Schristos         case OPT_PROV_CASES:
218b0d17251Schristos             if (!opt_provider(o))
219b0d17251Schristos                 goto end;
220a89c9211Schristos             break;
221a89c9211Schristos         }
222c7da899bSchristos     }
223b0d17251Schristos 
224b0d17251Schristos     /* Remaining args are files to digest. */
225c7da899bSchristos     argc = opt_num_rest();
226c7da899bSchristos     argv = opt_rest();
227218f7bfcSspz     if (keyfile != NULL && argc > 1) {
228c7da899bSchristos         BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
229218f7bfcSspz         goto end;
230218f7bfcSspz     }
231b0d17251Schristos     if (!app_RAND_load())
232b0d17251Schristos         goto end;
233b0d17251Schristos 
234b0d17251Schristos     if (digestname != NULL) {
235b0d17251Schristos         if (!opt_md(digestname, &md))
236b0d17251Schristos             goto opthelp;
237b0d17251Schristos     }
238218f7bfcSspz 
23913d40330Schristos     if (do_verify && sigfile == NULL) {
240635165faSspz         BIO_printf(bio_err,
241635165faSspz                    "No signature to verify: use the -signature option\n");
242a89c9211Schristos         goto end;
243a89c9211Schristos     }
244218f7bfcSspz     if (engine_impl)
245218f7bfcSspz         impl = e;
246a89c9211Schristos 
247a89c9211Schristos     in = BIO_new(BIO_s_file());
248a89c9211Schristos     bmd = BIO_new(BIO_f_md());
249b0d17251Schristos     if (in == NULL || bmd == NULL)
250635165faSspz         goto end;
251635165faSspz 
252635165faSspz     if (debug) {
253b0d17251Schristos         BIO_set_callback_ex(in, BIO_debug_callback_ex);
254a89c9211Schristos         /* needed for windows 3.1 */
255a89c9211Schristos         BIO_set_callback_arg(in, (char *)bio_err);
256a89c9211Schristos     }
257a89c9211Schristos 
258c7da899bSchristos     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
259a89c9211Schristos         BIO_printf(bio_err, "Error getting password\n");
260a89c9211Schristos         goto end;
261a89c9211Schristos     }
262a89c9211Schristos 
263a89c9211Schristos     if (out_bin == -1) {
26413d40330Schristos         if (keyfile != NULL)
265a89c9211Schristos             out_bin = 1;
266a89c9211Schristos         else
267a89c9211Schristos             out_bin = 0;
268a89c9211Schristos     }
269a89c9211Schristos 
270c7da899bSchristos     out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
271c7da899bSchristos     if (out == NULL)
272a89c9211Schristos         goto end;
273c7da899bSchristos 
27413d40330Schristos     if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
275b0d17251Schristos         BIO_printf(bio_err, "MAC and signing key cannot both be specified\n");
276a89c9211Schristos         goto end;
277a89c9211Schristos     }
278a89c9211Schristos 
27913d40330Schristos     if (keyfile != NULL) {
28013d40330Schristos         int type;
28113d40330Schristos 
282a89c9211Schristos         if (want_pub)
283b0d17251Schristos             sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
284a89c9211Schristos         else
285b0d17251Schristos             sigkey = load_key(keyfile, keyform, 0, passin, e, "private key");
28613d40330Schristos         if (sigkey == NULL) {
287635165faSspz             /*
288635165faSspz              * load_[pub]key() has already printed an appropriate message
289635165faSspz              */
290a89c9211Schristos             goto end;
291a89c9211Schristos         }
292b0d17251Schristos         type = EVP_PKEY_get_id(sigkey);
29313d40330Schristos         if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
29413d40330Schristos             /*
29513d40330Schristos              * We implement PureEdDSA for these which doesn't have a separate
29613d40330Schristos              * digest, and only supports one shot.
29713d40330Schristos              */
29813d40330Schristos             BIO_printf(bio_err, "Key type not supported for this operation\n");
29913d40330Schristos             goto end;
30013d40330Schristos         }
301a89c9211Schristos     }
302a89c9211Schristos 
30313d40330Schristos     if (mac_name != NULL) {
304a89c9211Schristos         EVP_PKEY_CTX *mac_ctx = NULL;
305b0d17251Schristos 
306b0d17251Schristos         if (!init_gen_str(&mac_ctx, mac_name, impl, 0, NULL, NULL))
307a89c9211Schristos             goto end;
308b0d17251Schristos         if (macopts != NULL) {
309b0d17251Schristos             for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
310b0d17251Schristos                 char *macopt = sk_OPENSSL_STRING_value(macopts, i);
311b0d17251Schristos 
312b0d17251Schristos                 if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
313b0d17251Schristos                     EVP_PKEY_CTX_free(mac_ctx);
314b0d17251Schristos                     BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt);
315b0d17251Schristos                     goto end;
316b0d17251Schristos                 }
317b0d17251Schristos             }
318b0d17251Schristos         }
319b0d17251Schristos 
320b0d17251Schristos         sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */);
321b0d17251Schristos         /* Verbose output would make external-tests gost-engine fail */
322b0d17251Schristos         EVP_PKEY_CTX_free(mac_ctx);
3234778aedeSchristos         if (sigkey == NULL)
3244778aedeSchristos             goto end;
325a89c9211Schristos     }
326a89c9211Schristos 
32713d40330Schristos     if (hmac_key != NULL) {
328b0d17251Schristos         if (md == NULL) {
329b0d17251Schristos             md = (EVP_MD *)EVP_sha256();
330b0d17251Schristos             digestname = SN_sha256;
331b0d17251Schristos         }
33213d40330Schristos         sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
333b0d17251Schristos                                               (unsigned char *)hmac_key,
334b0d17251Schristos                                               strlen(hmac_key));
33513d40330Schristos         if (sigkey == NULL)
336a89c9211Schristos             goto end;
337a89c9211Schristos     }
338a89c9211Schristos 
33913d40330Schristos     if (sigkey != NULL) {
340a89c9211Schristos         EVP_MD_CTX *mctx = NULL;
341a89c9211Schristos         EVP_PKEY_CTX *pctx = NULL;
342b0d17251Schristos         int res;
343b0d17251Schristos 
34421497c5cSchristos         if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
345a89c9211Schristos             BIO_printf(bio_err, "Error getting context\n");
346a89c9211Schristos             goto end;
347a89c9211Schristos         }
348a89c9211Schristos         if (do_verify)
349b0d17251Schristos             if (impl == NULL)
350b0d17251Schristos                 res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname,
351b0d17251Schristos                                               app_get0_libctx(),
352b0d17251Schristos                                               app_get0_propq(), sigkey, NULL);
353a89c9211Schristos             else
354b0d17251Schristos                 res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
355b0d17251Schristos         else
356b0d17251Schristos             if (impl == NULL)
357b0d17251Schristos                 res = EVP_DigestSignInit_ex(mctx, &pctx, digestname,
358b0d17251Schristos                                             app_get0_libctx(),
359b0d17251Schristos                                             app_get0_propq(), sigkey, NULL);
360b0d17251Schristos             else
361b0d17251Schristos                 res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
362b0d17251Schristos         if (res == 0) {
363a89c9211Schristos             BIO_printf(bio_err, "Error setting context\n");
364a89c9211Schristos             goto end;
365a89c9211Schristos         }
36613d40330Schristos         if (sigopts != NULL) {
367635165faSspz             for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
368b0d17251Schristos                 char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
369b0d17251Schristos 
370635165faSspz                 if (pkey_ctrl_string(pctx, sigopt) <= 0) {
371b0d17251Schristos                     BIO_printf(bio_err, "Signature parameter error \"%s\"\n",
372b0d17251Schristos                                sigopt);
373a89c9211Schristos                     goto end;
374a89c9211Schristos                 }
375a89c9211Schristos             }
376a89c9211Schristos         }
377a89c9211Schristos     }
378a89c9211Schristos     /* we use md as a filter, reading from 'in' */
379635165faSspz     else {
380218f7bfcSspz         EVP_MD_CTX *mctx = NULL;
38121497c5cSchristos         if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
382218f7bfcSspz             BIO_printf(bio_err, "Error getting context\n");
383218f7bfcSspz             goto end;
384218f7bfcSspz         }
385a89c9211Schristos         if (md == NULL)
386b0d17251Schristos             md = (EVP_MD *)EVP_sha256();
387218f7bfcSspz         if (!EVP_DigestInit_ex(mctx, md, impl)) {
388c7da899bSchristos             BIO_printf(bio_err, "Error setting digest\n");
389a89c9211Schristos             goto end;
390a89c9211Schristos         }
391a89c9211Schristos     }
392a89c9211Schristos 
39313d40330Schristos     if (sigfile != NULL && sigkey != NULL) {
394c7da899bSchristos         BIO *sigbio = BIO_new_file(sigfile, "rb");
395b0d17251Schristos 
39613d40330Schristos         if (sigbio == NULL) {
397635165faSspz             BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
398635165faSspz             goto end;
399635165faSspz         }
400b0d17251Schristos         siglen = EVP_PKEY_get_size(sigkey);
401c7da899bSchristos         sigbuf = app_malloc(siglen, "signature buffer");
402a89c9211Schristos         siglen = BIO_read(sigbio, sigbuf, siglen);
403a89c9211Schristos         BIO_free(sigbio);
404a89c9211Schristos         if (siglen <= 0) {
405635165faSspz             BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
406a89c9211Schristos             goto end;
407a89c9211Schristos         }
408a89c9211Schristos     }
409a89c9211Schristos     inp = BIO_push(bmd, in);
410a89c9211Schristos 
411635165faSspz     if (md == NULL) {
412a89c9211Schristos         EVP_MD_CTX *tctx;
413b0d17251Schristos 
414a89c9211Schristos         BIO_get_md_ctx(bmd, &tctx);
415b0d17251Schristos         md = EVP_MD_CTX_get1_md(tctx);
416b0d17251Schristos     }
417b0d17251Schristos     if (md != NULL)
418b0d17251Schristos         md_name = EVP_MD_get0_name(md);
419b0d17251Schristos 
420b0d17251Schristos     if (xoflen > 0) {
421b0d17251Schristos         if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) {
422b0d17251Schristos             BIO_printf(bio_err, "Length can only be specified for XOF\n");
423b0d17251Schristos             goto end;
424b0d17251Schristos         }
425b0d17251Schristos         /*
426b0d17251Schristos          * Signing using XOF is not supported by any algorithms currently since
427b0d17251Schristos          * each algorithm only calls EVP_DigestFinal_ex() in their sign_final
428b0d17251Schristos          * and verify_final methods.
429b0d17251Schristos          */
430b0d17251Schristos         if (sigkey != NULL) {
431b0d17251Schristos             BIO_printf(bio_err, "Signing key cannot be specified for XOF\n");
432b0d17251Schristos             goto end;
433b0d17251Schristos         }
434a89c9211Schristos     }
435a89c9211Schristos 
436635165faSspz     if (argc == 0) {
437a89c9211Schristos         BIO_set_fp(in, stdin, BIO_NOCLOSE);
438b0d17251Schristos         ret = do_fp(out, buf, inp, separator, out_bin, xoflen, sigkey, sigbuf,
439b0d17251Schristos                     siglen, NULL, md_name, "stdin");
440635165faSspz     } else {
441b0d17251Schristos         const char *sig_name = NULL;
442b0d17251Schristos 
443b0d17251Schristos         if (out_bin == 0) {
444b0d17251Schristos             if (sigkey != NULL)
445b0d17251Schristos                 sig_name = EVP_PKEY_get0_type_name(sigkey);
446a89c9211Schristos         }
447b0d17251Schristos         ret = EXIT_SUCCESS;
448635165faSspz         for (i = 0; i < argc; i++) {
449635165faSspz             if (BIO_read_filename(in, argv[i]) <= 0) {
450a89c9211Schristos                 perror(argv[i]);
451b0d17251Schristos                 ret = EXIT_FAILURE;
452a89c9211Schristos                 continue;
45313d40330Schristos             } else {
454b0d17251Schristos                 if (do_fp(out, buf, inp, separator, out_bin, xoflen,
455b0d17251Schristos                           sigkey, sigbuf, siglen, sig_name, md_name, argv[i]))
456b0d17251Schristos                     ret = EXIT_FAILURE;
45713d40330Schristos             }
458a89c9211Schristos             (void)BIO_reset(bmd);
459a89c9211Schristos         }
460a89c9211Schristos     }
461a89c9211Schristos  end:
462b0d17251Schristos     if (ret != EXIT_SUCCESS)
463b0d17251Schristos         ERR_print_errors(bio_err);
464c7da899bSchristos     OPENSSL_clear_free(buf, BUFSIZE);
465635165faSspz     BIO_free(in);
466a89c9211Schristos     OPENSSL_free(passin);
467a89c9211Schristos     BIO_free_all(out);
468b0d17251Schristos     EVP_MD_free(md);
469a89c9211Schristos     EVP_PKEY_free(sigkey);
47086adef1bSchristos     sk_OPENSSL_STRING_free(sigopts);
47186adef1bSchristos     sk_OPENSSL_STRING_free(macopts);
472635165faSspz     OPENSSL_free(sigbuf);
473635165faSspz     BIO_free(bmd);
47434505c60Sspz     release_engine(e);
47513d40330Schristos     return ret;
476a89c9211Schristos }
477a89c9211Schristos 
4787d004720Schristos static void show_digests(const OBJ_NAME *name, void *arg)
4797d004720Schristos {
4807d004720Schristos     struct doall_dgst_digests *dec = (struct doall_dgst_digests *)arg;
481*97e3c585Schristos     EVP_MD *md = NULL;
4827d004720Schristos 
4837d004720Schristos     /* Filter out signed digests (a.k.a signature algorithms) */
4847d004720Schristos     if (strstr(name->name, "rsa") != NULL || strstr(name->name, "RSA") != NULL)
4857d004720Schristos         return;
4867d004720Schristos 
4877d004720Schristos     if (!islower((unsigned char)*name->name))
4887d004720Schristos         return;
4897d004720Schristos 
4907d004720Schristos     /* Filter out message digests that we cannot use */
491b0d17251Schristos     md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq());
4924170684fSchristos     if (md == NULL) {
493*97e3c585Schristos         if (EVP_get_digestbyname(name->name) == NULL)
4947d004720Schristos             return;
4954170684fSchristos     }
4967d004720Schristos 
4977d004720Schristos     BIO_printf(dec->bio, "-%-25s", name->name);
4987d004720Schristos     if (++dec->n == 3) {
4997d004720Schristos         BIO_printf(dec->bio, "\n");
5007d004720Schristos         dec->n = 0;
5017d004720Schristos     } else {
5027d004720Schristos         BIO_printf(dec->bio, " ");
5037d004720Schristos     }
504*97e3c585Schristos 
505*97e3c585Schristos     EVP_MD_free(md);
5067d004720Schristos }
5077d004720Schristos 
5087d004720Schristos /*
5097d004720Schristos  * The newline_escape_filename function performs newline escaping for any
5107d004720Schristos  * filename that contains a newline.  This function also takes a pointer
5117d004720Schristos  * to backslash. The backslash pointer is a flag to indicating whether a newline
5127d004720Schristos  * is present in the filename.  If a newline is present, the backslash flag is
5137d004720Schristos  * set and the output format will contain a backslash at the beginning of the
5147d004720Schristos  * digest output. This output format is to replicate the output format found
5157d004720Schristos  * in the '*sum' checksum programs. This aims to preserve backward
5167d004720Schristos  * compatibility.
5177d004720Schristos  */
5187d004720Schristos static const char *newline_escape_filename(const char *file, int * backslash)
5197d004720Schristos {
5207d004720Schristos     size_t i, e = 0, length = strlen(file), newline_count = 0, mem_len = 0;
5217d004720Schristos     char *file_cpy = NULL;
5227d004720Schristos 
5237d004720Schristos     for (i = 0; i < length; i++)
5247d004720Schristos         if (file[i] == '\n')
5257d004720Schristos             newline_count++;
5267d004720Schristos 
5277d004720Schristos     mem_len = length + newline_count + 1;
5287d004720Schristos     file_cpy = app_malloc(mem_len, file);
5297d004720Schristos     i = 0;
5307d004720Schristos 
5317d004720Schristos     while(e < length) {
5327d004720Schristos         const char c = file[e];
5337d004720Schristos         if (c == '\n') {
5347d004720Schristos             file_cpy[i++] = '\\';
5357d004720Schristos             file_cpy[i++] = 'n';
5367d004720Schristos             *backslash = 1;
5377d004720Schristos         } else {
5387d004720Schristos             file_cpy[i++] = c;
5397d004720Schristos         }
5407d004720Schristos         e++;
5417d004720Schristos     }
5427d004720Schristos     file_cpy[i] = '\0';
5437d004720Schristos     return (const char*)file_cpy;
5447d004720Schristos }
5457d004720Schristos 
5467d004720Schristos 
547b0d17251Schristos int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen,
548a89c9211Schristos           EVP_PKEY *key, unsigned char *sigin, int siglen,
549a89c9211Schristos           const char *sig_name, const char *md_name,
550c7da899bSchristos           const char *file)
551a89c9211Schristos {
5527d004720Schristos     size_t len = BUFSIZE;
553b0d17251Schristos     int i, backslash = 0, ret = EXIT_FAILURE;
554b0d17251Schristos     unsigned char *allocated_buf = NULL;
555a89c9211Schristos 
5564ce06407Schristos     while (BIO_pending(bp) || !BIO_eof(bp)) {
557a89c9211Schristos         i = BIO_read(bp, (char *)buf, BUFSIZE);
558635165faSspz         if (i < 0) {
559b0d17251Schristos             BIO_printf(bio_err, "Read error in %s\n", file);
5607d004720Schristos             goto end;
561a89c9211Schristos         }
562635165faSspz         if (i == 0)
563635165faSspz             break;
564a89c9211Schristos     }
56513d40330Schristos     if (sigin != NULL) {
566a89c9211Schristos         EVP_MD_CTX *ctx;
567a89c9211Schristos         BIO_get_md_ctx(bp, &ctx);
568a89c9211Schristos         i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
56913d40330Schristos         if (i > 0) {
570a89c9211Schristos             BIO_printf(out, "Verified OK\n");
57113d40330Schristos         } else if (i == 0) {
572b0d17251Schristos             BIO_printf(out, "Verification failure\n");
5737d004720Schristos             goto end;
574635165faSspz         } else {
575b0d17251Schristos             BIO_printf(bio_err, "Error verifying data\n");
5767d004720Schristos             goto end;
577a89c9211Schristos         }
578b0d17251Schristos         ret = EXIT_SUCCESS;
5797d004720Schristos         goto end;
580a89c9211Schristos     }
58113d40330Schristos     if (key != NULL) {
582a89c9211Schristos         EVP_MD_CTX *ctx;
583b0d17251Schristos         size_t tmplen;
584b0d17251Schristos 
585a89c9211Schristos         BIO_get_md_ctx(bp, &ctx);
586b0d17251Schristos         if (!EVP_DigestSignFinal(ctx, NULL, &tmplen)) {
587b0d17251Schristos             BIO_printf(bio_err, "Error getting maximum length of signed data\n");
588b0d17251Schristos             goto end;
589b0d17251Schristos         }
590b0d17251Schristos         if (tmplen > BUFSIZE) {
591b0d17251Schristos             len = tmplen;
592b0d17251Schristos             allocated_buf = app_malloc(len, "Signature buffer");
593b0d17251Schristos             buf = allocated_buf;
5947d004720Schristos         }
595635165faSspz         if (!EVP_DigestSignFinal(ctx, buf, &len)) {
596b0d17251Schristos             BIO_printf(bio_err, "Error signing data\n");
597b0d17251Schristos             goto end;
598b0d17251Schristos         }
599b0d17251Schristos     } else if (xoflen > 0) {
600b0d17251Schristos         EVP_MD_CTX *ctx;
601b0d17251Schristos 
602b0d17251Schristos         len = xoflen;
603b0d17251Schristos         if (len > BUFSIZE) {
604b0d17251Schristos             allocated_buf = app_malloc(len, "Digest buffer");
605b0d17251Schristos             buf = allocated_buf;
606b0d17251Schristos         }
607b0d17251Schristos 
608b0d17251Schristos         BIO_get_md_ctx(bp, &ctx);
609b0d17251Schristos 
610b0d17251Schristos         if (!EVP_DigestFinalXOF(ctx, buf, len)) {
611b0d17251Schristos             BIO_printf(bio_err, "Error Digesting Data\n");
6127d004720Schristos             goto end;
613a89c9211Schristos         }
614635165faSspz     } else {
615a89c9211Schristos         len = BIO_gets(bp, (char *)buf, BUFSIZE);
616b0d17251Schristos         if ((int)len < 0)
6177d004720Schristos             goto end;
618a89c9211Schristos     }
619a89c9211Schristos 
62013d40330Schristos     if (binout) {
621635165faSspz         BIO_write(out, buf, len);
62213d40330Schristos     } else if (sep == 2) {
6237d004720Schristos         file = newline_escape_filename(file, &backslash);
6247d004720Schristos 
6257d004720Schristos         if (backslash == 1)
6267d004720Schristos             BIO_puts(out, "\\");
6277d004720Schristos 
628cef2ee70Schristos         for (i = 0; i < (int)len; i++)
629cef2ee70Schristos             BIO_printf(out, "%02x", buf[i]);
6307d004720Schristos 
631cef2ee70Schristos         BIO_printf(out, " *%s\n", file);
6327d004720Schristos         OPENSSL_free((char *)file);
633635165faSspz     } else {
63413d40330Schristos         if (sig_name != NULL) {
635218f7bfcSspz             BIO_puts(out, sig_name);
63613d40330Schristos             if (md_name != NULL)
637218f7bfcSspz                 BIO_printf(out, "-%s", md_name);
638218f7bfcSspz             BIO_printf(out, "(%s)= ", file);
63913d40330Schristos         } else if (md_name != NULL) {
640a89c9211Schristos             BIO_printf(out, "%s(%s)= ", md_name, file);
64113d40330Schristos         } else {
642a89c9211Schristos             BIO_printf(out, "(%s)= ", file);
64313d40330Schristos         }
644635165faSspz         for (i = 0; i < (int)len; i++) {
645a89c9211Schristos             if (sep && (i != 0))
646a89c9211Schristos                 BIO_printf(out, ":");
647a89c9211Schristos             BIO_printf(out, "%02x", buf[i]);
648a89c9211Schristos         }
649a89c9211Schristos         BIO_printf(out, "\n");
650a89c9211Schristos     }
6517d004720Schristos 
652b0d17251Schristos     ret = EXIT_SUCCESS;
6537d004720Schristos  end:
654b0d17251Schristos     if (allocated_buf != NULL)
655b0d17251Schristos         OPENSSL_clear_free(allocated_buf, len);
6567d004720Schristos 
6577d004720Schristos     return ret;
658a89c9211Schristos }
659