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