Home | History | Annotate | Line # | Download | only in apps
      1 /*
      2  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <stdio.h>
     11 #include <string.h>
     12 #include <stdlib.h>
     13 #include "apps.h"
     14 #include "progs.h"
     15 #include <openssl/bio.h>
     16 #include <openssl/err.h>
     17 #include <openssl/evp.h>
     18 #include <openssl/objects.h>
     19 #include <openssl/x509.h>
     20 #include <openssl/pem.h>
     21 #include <openssl/hmac.h>
     22 #include <ctype.h>
     23 
     24 #undef BUFSIZE
     25 #define BUFSIZE 1024*8
     26 
     27 int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
     28           EVP_PKEY *key, unsigned char *sigin, int siglen,
     29           const char *sig_name, const char *md_name,
     30           const char *file);
     31 static void show_digests(const OBJ_NAME *name, void *bio_);
     32 
     33 struct doall_dgst_digests {
     34     BIO *bio;
     35     int n;
     36 };
     37 
     38 typedef enum OPTION_choice {
     39     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_LIST,
     40     OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
     41     OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
     42     OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
     43     OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT,
     44     OPT_DIGEST,
     45     OPT_R_ENUM
     46 } OPTION_CHOICE;
     47 
     48 const OPTIONS dgst_options[] = {
     49     {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"},
     50     {OPT_HELP_STR, 1, '-',
     51         "  file... files to digest (default is stdin)\n"},
     52     {"help", OPT_HELP, '-', "Display this summary"},
     53     {"list", OPT_LIST, '-', "List digests"},
     54     {"c", OPT_C, '-', "Print the digest with separating colons"},
     55     {"r", OPT_R, '-', "Print the digest in coreutils format"},
     56     {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
     57     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     58     {"sign", OPT_SIGN, 's', "Sign digest using private key"},
     59     {"verify", OPT_VERIFY, 's',
     60      "Verify a signature using public key"},
     61     {"prverify", OPT_PRVERIFY, 's',
     62      "Verify a signature using private key"},
     63     {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
     64     {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"},
     65     {"hex", OPT_HEX, '-', "Print as hex dump"},
     66     {"binary", OPT_BINARY, '-', "Print in binary form"},
     67     {"d", OPT_DEBUG, '-', "Print debug info"},
     68     {"debug", OPT_DEBUG, '-', "Print debug info"},
     69     {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
     70      "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
     71     {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
     72     {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
     73     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
     74     {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
     75     {"", OPT_DIGEST, '-', "Any supported digest"},
     76     OPT_R_OPTIONS,
     77 #ifndef OPENSSL_NO_ENGINE
     78     {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
     79     {"engine_impl", OPT_ENGINE_IMPL, '-',
     80      "Also use engine given by -engine for digest operations"},
     81 #endif
     82     {NULL}
     83 };
     84 
     85 int dgst_main(int argc, char **argv)
     86 {
     87     BIO *in = NULL, *inp, *bmd = NULL, *out = NULL;
     88     ENGINE *e = NULL, *impl = NULL;
     89     EVP_PKEY *sigkey = NULL;
     90     STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
     91     char *hmac_key = NULL;
     92     char *mac_name = NULL;
     93     char *passinarg = NULL, *passin = NULL;
     94     const EVP_MD *md = NULL, *m;
     95     const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
     96     const char *sigfile = NULL;
     97     OPTION_CHOICE o;
     98     int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0;
     99     int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0;
    100     unsigned char *buf = NULL, *sigbuf = NULL;
    101     int engine_impl = 0;
    102     struct doall_dgst_digests dec;
    103 
    104     prog = opt_progname(argv[0]);
    105     buf = app_malloc(BUFSIZE, "I/O buffer");
    106     md = EVP_get_digestbyname(prog);
    107 
    108     prog = opt_init(argc, argv, dgst_options);
    109     while ((o = opt_next()) != OPT_EOF) {
    110         switch (o) {
    111         case OPT_EOF:
    112         case OPT_ERR:
    113  opthelp:
    114             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
    115             goto end;
    116         case OPT_HELP:
    117             opt_help(dgst_options);
    118             ret = 0;
    119             goto end;
    120         case OPT_LIST:
    121             BIO_printf(bio_out, "Supported digests:\n");
    122             dec.bio = bio_out;
    123             dec.n = 0;
    124             OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
    125                                    show_digests, &dec);
    126             BIO_printf(bio_out, "\n");
    127             ret = 0;
    128             goto end;
    129         case OPT_C:
    130             separator = 1;
    131             break;
    132         case OPT_R:
    133             separator = 2;
    134             break;
    135         case OPT_R_CASES:
    136             if (!opt_rand(o))
    137                 goto end;
    138             break;
    139         case OPT_OUT:
    140             outfile = opt_arg();
    141             break;
    142         case OPT_SIGN:
    143             keyfile = opt_arg();
    144             break;
    145         case OPT_PASSIN:
    146             passinarg = opt_arg();
    147             break;
    148         case OPT_VERIFY:
    149             keyfile = opt_arg();
    150             want_pub = do_verify = 1;
    151             break;
    152         case OPT_PRVERIFY:
    153             keyfile = opt_arg();
    154             do_verify = 1;
    155             break;
    156         case OPT_SIGNATURE:
    157             sigfile = opt_arg();
    158             break;
    159         case OPT_KEYFORM:
    160             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
    161                 goto opthelp;
    162             break;
    163         case OPT_ENGINE:
    164             e = setup_engine(opt_arg(), 0);
    165             break;
    166         case OPT_ENGINE_IMPL:
    167             engine_impl = 1;
    168             break;
    169         case OPT_HEX:
    170             out_bin = 0;
    171             break;
    172         case OPT_BINARY:
    173             out_bin = 1;
    174             break;
    175         case OPT_DEBUG:
    176             debug = 1;
    177             break;
    178         case OPT_FIPS_FINGERPRINT:
    179             hmac_key = "etaonrishdlcupfm";
    180             break;
    181         case OPT_HMAC:
    182             hmac_key = opt_arg();
    183             break;
    184         case OPT_MAC:
    185             mac_name = opt_arg();
    186             break;
    187         case OPT_SIGOPT:
    188             if (!sigopts)
    189                 sigopts = sk_OPENSSL_STRING_new_null();
    190             if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
    191                 goto opthelp;
    192             break;
    193         case OPT_MACOPT:
    194             if (!macopts)
    195                 macopts = sk_OPENSSL_STRING_new_null();
    196             if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg()))
    197                 goto opthelp;
    198             break;
    199         case OPT_DIGEST:
    200             if (!opt_md(opt_unknown(), &m))
    201                 goto opthelp;
    202             md = m;
    203             break;
    204         }
    205     }
    206     argc = opt_num_rest();
    207     argv = opt_rest();
    208     if (keyfile != NULL && argc > 1) {
    209         BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
    210         goto end;
    211     }
    212 
    213     if (do_verify && sigfile == NULL) {
    214         BIO_printf(bio_err,
    215                    "No signature to verify: use the -signature option\n");
    216         goto end;
    217     }
    218     if (engine_impl)
    219         impl = e;
    220 
    221     in = BIO_new(BIO_s_file());
    222     bmd = BIO_new(BIO_f_md());
    223     if ((in == NULL) || (bmd == NULL)) {
    224         ERR_print_errors(bio_err);
    225         goto end;
    226     }
    227 
    228     if (debug) {
    229         BIO_set_callback(in, BIO_debug_callback);
    230         /* needed for windows 3.1 */
    231         BIO_set_callback_arg(in, (char *)bio_err);
    232     }
    233 
    234     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
    235         BIO_printf(bio_err, "Error getting password\n");
    236         goto end;
    237     }
    238 
    239     if (out_bin == -1) {
    240         if (keyfile != NULL)
    241             out_bin = 1;
    242         else
    243             out_bin = 0;
    244     }
    245 
    246     out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
    247     if (out == NULL)
    248         goto end;
    249 
    250     if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
    251         BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
    252         goto end;
    253     }
    254 
    255     if (keyfile != NULL) {
    256         int type;
    257 
    258         if (want_pub)
    259             sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file");
    260         else
    261             sigkey = load_key(keyfile, keyform, 0, passin, e, "key file");
    262         if (sigkey == NULL) {
    263             /*
    264              * load_[pub]key() has already printed an appropriate message
    265              */
    266             goto end;
    267         }
    268         type = EVP_PKEY_id(sigkey);
    269         if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
    270             /*
    271              * We implement PureEdDSA for these which doesn't have a separate
    272              * digest, and only supports one shot.
    273              */
    274             BIO_printf(bio_err, "Key type not supported for this operation\n");
    275             goto end;
    276         }
    277     }
    278 
    279     if (mac_name != NULL) {
    280         EVP_PKEY_CTX *mac_ctx = NULL;
    281         int r = 0;
    282         if (!init_gen_str(&mac_ctx, mac_name, impl, 0))
    283             goto mac_end;
    284         if (macopts != NULL) {
    285             char *macopt;
    286             for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
    287                 macopt = sk_OPENSSL_STRING_value(macopts, i);
    288                 if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
    289                     BIO_printf(bio_err,
    290                                "MAC parameter error \"%s\"\n", macopt);
    291                     ERR_print_errors(bio_err);
    292                     goto mac_end;
    293                 }
    294             }
    295         }
    296         if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
    297             BIO_puts(bio_err, "Error generating key\n");
    298             ERR_print_errors(bio_err);
    299             goto mac_end;
    300         }
    301         r = 1;
    302  mac_end:
    303         EVP_PKEY_CTX_free(mac_ctx);
    304         if (r == 0)
    305             goto end;
    306     }
    307 
    308     if (hmac_key != NULL) {
    309         sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
    310                                               (unsigned char *)hmac_key, -1);
    311         if (sigkey == NULL)
    312             goto end;
    313     }
    314 
    315     if (sigkey != NULL) {
    316         EVP_MD_CTX *mctx = NULL;
    317         EVP_PKEY_CTX *pctx = NULL;
    318         int r;
    319         if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
    320             BIO_printf(bio_err, "Error getting context\n");
    321             ERR_print_errors(bio_err);
    322             goto end;
    323         }
    324         if (do_verify)
    325             r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
    326         else
    327             r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
    328         if (!r) {
    329             BIO_printf(bio_err, "Error setting context\n");
    330             ERR_print_errors(bio_err);
    331             goto end;
    332         }
    333         if (sigopts != NULL) {
    334             char *sigopt;
    335             for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
    336                 sigopt = sk_OPENSSL_STRING_value(sigopts, i);
    337                 if (pkey_ctrl_string(pctx, sigopt) <= 0) {
    338                     BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
    339                     ERR_print_errors(bio_err);
    340                     goto end;
    341                 }
    342             }
    343         }
    344     }
    345     /* we use md as a filter, reading from 'in' */
    346     else {
    347         EVP_MD_CTX *mctx = NULL;
    348         if (BIO_get_md_ctx(bmd, &mctx) <= 0) {
    349             BIO_printf(bio_err, "Error getting context\n");
    350             ERR_print_errors(bio_err);
    351             goto end;
    352         }
    353         if (md == NULL)
    354             md = EVP_sha256();
    355         if (!EVP_DigestInit_ex(mctx, md, impl)) {
    356             BIO_printf(bio_err, "Error setting digest\n");
    357             ERR_print_errors(bio_err);
    358             goto end;
    359         }
    360     }
    361 
    362     if (sigfile != NULL && sigkey != NULL) {
    363         BIO *sigbio = BIO_new_file(sigfile, "rb");
    364         if (sigbio == NULL) {
    365             BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
    366             ERR_print_errors(bio_err);
    367             goto end;
    368         }
    369         siglen = EVP_PKEY_size(sigkey);
    370         sigbuf = app_malloc(siglen, "signature buffer");
    371         siglen = BIO_read(sigbio, sigbuf, siglen);
    372         BIO_free(sigbio);
    373         if (siglen <= 0) {
    374             BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
    375             ERR_print_errors(bio_err);
    376             goto end;
    377         }
    378     }
    379     inp = BIO_push(bmd, in);
    380 
    381     if (md == NULL) {
    382         EVP_MD_CTX *tctx;
    383         BIO_get_md_ctx(bmd, &tctx);
    384         md = EVP_MD_CTX_md(tctx);
    385     }
    386 
    387     if (argc == 0) {
    388         BIO_set_fp(in, stdin, BIO_NOCLOSE);
    389         ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
    390                     siglen, NULL, NULL, "stdin");
    391     } else {
    392         const char *md_name = NULL, *sig_name = NULL;
    393         if (!out_bin) {
    394             if (sigkey != NULL) {
    395                 const EVP_PKEY_ASN1_METHOD *ameth;
    396                 ameth = EVP_PKEY_get0_asn1(sigkey);
    397                 if (ameth)
    398                     EVP_PKEY_asn1_get0_info(NULL, NULL,
    399                                             NULL, NULL, &sig_name, ameth);
    400             }
    401             if (md != NULL)
    402                 md_name = EVP_MD_name(md);
    403         }
    404         ret = 0;
    405         for (i = 0; i < argc; i++) {
    406             int r;
    407             if (BIO_read_filename(in, argv[i]) <= 0) {
    408                 perror(argv[i]);
    409                 ret++;
    410                 continue;
    411             } else {
    412                 r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
    413                           siglen, sig_name, md_name, argv[i]);
    414             }
    415             if (r)
    416                 ret = r;
    417             (void)BIO_reset(bmd);
    418         }
    419     }
    420  end:
    421     OPENSSL_clear_free(buf, BUFSIZE);
    422     BIO_free(in);
    423     OPENSSL_free(passin);
    424     BIO_free_all(out);
    425     EVP_PKEY_free(sigkey);
    426     sk_OPENSSL_STRING_free(sigopts);
    427     sk_OPENSSL_STRING_free(macopts);
    428     OPENSSL_free(sigbuf);
    429     BIO_free(bmd);
    430     release_engine(e);
    431     return ret;
    432 }
    433 
    434 static void show_digests(const OBJ_NAME *name, void *arg)
    435 {
    436     struct doall_dgst_digests *dec = (struct doall_dgst_digests *)arg;
    437     const EVP_MD *md = NULL;
    438 
    439     /* Filter out signed digests (a.k.a signature algorithms) */
    440     if (strstr(name->name, "rsa") != NULL || strstr(name->name, "RSA") != NULL)
    441         return;
    442 
    443     if (!islower((unsigned char)*name->name))
    444         return;
    445 
    446     /* Filter out message digests that we cannot use */
    447     md = EVP_get_digestbyname(name->name);
    448     if (md == NULL)
    449         return;
    450 
    451     BIO_printf(dec->bio, "-%-25s", name->name);
    452     if (++dec->n == 3) {
    453         BIO_printf(dec->bio, "\n");
    454         dec->n = 0;
    455     } else {
    456         BIO_printf(dec->bio, " ");
    457     }
    458 }
    459 
    460 /*
    461  * The newline_escape_filename function performs newline escaping for any
    462  * filename that contains a newline.  This function also takes a pointer
    463  * to backslash. The backslash pointer is a flag to indicating whether a newline
    464  * is present in the filename.  If a newline is present, the backslash flag is
    465  * set and the output format will contain a backslash at the beginning of the
    466  * digest output. This output format is to replicate the output format found
    467  * in the '*sum' checksum programs. This aims to preserve backward
    468  * compatibility.
    469  */
    470 static const char *newline_escape_filename(const char *file, int * backslash)
    471 {
    472     size_t i, e = 0, length = strlen(file), newline_count = 0, mem_len = 0;
    473     char *file_cpy = NULL;
    474 
    475     for (i = 0; i < length; i++)
    476         if (file[i] == '\n')
    477             newline_count++;
    478 
    479     mem_len = length + newline_count + 1;
    480     file_cpy = app_malloc(mem_len, file);
    481     i = 0;
    482 
    483     while(e < length) {
    484         const char c = file[e];
    485         if (c == '\n') {
    486             file_cpy[i++] = '\\';
    487             file_cpy[i++] = 'n';
    488             *backslash = 1;
    489         } else {
    490             file_cpy[i++] = c;
    491         }
    492         e++;
    493     }
    494     file_cpy[i] = '\0';
    495     return (const char*)file_cpy;
    496 }
    497 
    498 
    499 int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
    500           EVP_PKEY *key, unsigned char *sigin, int siglen,
    501           const char *sig_name, const char *md_name,
    502           const char *file)
    503 {
    504     size_t len = BUFSIZE;
    505     int i, backslash = 0, ret = 1;
    506     unsigned char *sigbuf = NULL;
    507 
    508     while (BIO_pending(bp) || !BIO_eof(bp)) {
    509         i = BIO_read(bp, (char *)buf, BUFSIZE);
    510         if (i < 0) {
    511             BIO_printf(bio_err, "Read Error in %s\n", file);
    512             ERR_print_errors(bio_err);
    513             goto end;
    514         }
    515         if (i == 0)
    516             break;
    517     }
    518     if (sigin != NULL) {
    519         EVP_MD_CTX *ctx;
    520         BIO_get_md_ctx(bp, &ctx);
    521         i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
    522         if (i > 0) {
    523             BIO_printf(out, "Verified OK\n");
    524         } else if (i == 0) {
    525             BIO_printf(out, "Verification Failure\n");
    526             goto end;
    527         } else {
    528             BIO_printf(bio_err, "Error Verifying Data\n");
    529             ERR_print_errors(bio_err);
    530             goto end;
    531         }
    532         ret = 0;
    533         goto end;
    534     }
    535     if (key != NULL) {
    536         EVP_MD_CTX *ctx;
    537         int pkey_len;
    538         BIO_get_md_ctx(bp, &ctx);
    539         pkey_len = EVP_PKEY_size(key);
    540         if (pkey_len > BUFSIZE) {
    541             len = pkey_len;
    542             sigbuf = app_malloc(len, "Signature buffer");
    543             buf = sigbuf;
    544         }
    545         if (!EVP_DigestSignFinal(ctx, buf, &len)) {
    546             BIO_printf(bio_err, "Error Signing Data\n");
    547             ERR_print_errors(bio_err);
    548             goto end;
    549         }
    550     } else {
    551         len = BIO_gets(bp, (char *)buf, BUFSIZE);
    552         if ((int)len < 0) {
    553             ERR_print_errors(bio_err);
    554             goto end;
    555         }
    556     }
    557 
    558     if (binout) {
    559         BIO_write(out, buf, len);
    560     } else if (sep == 2) {
    561         file = newline_escape_filename(file, &backslash);
    562 
    563         if (backslash == 1)
    564             BIO_puts(out, "\\");
    565 
    566         for (i = 0; i < (int)len; i++)
    567             BIO_printf(out, "%02x", buf[i]);
    568 
    569         BIO_printf(out, " *%s\n", file);
    570         OPENSSL_free((char *)file);
    571     } else {
    572         if (sig_name != NULL) {
    573             BIO_puts(out, sig_name);
    574             if (md_name != NULL)
    575                 BIO_printf(out, "-%s", md_name);
    576             BIO_printf(out, "(%s)= ", file);
    577         } else if (md_name != NULL) {
    578             BIO_printf(out, "%s(%s)= ", md_name, file);
    579         } else {
    580             BIO_printf(out, "(%s)= ", file);
    581         }
    582         for (i = 0; i < (int)len; i++) {
    583             if (sep && (i != 0))
    584                 BIO_printf(out, ":");
    585             BIO_printf(out, "%02x", buf[i]);
    586         }
    587         BIO_printf(out, "\n");
    588     }
    589 
    590     ret = 0;
    591  end:
    592     if (sigbuf != NULL)
    593         OPENSSL_clear_free(sigbuf, len);
    594 
    595     return ret;
    596 }
    597