X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=apps%2Fdgst.c;h=fe05b312d7b2dae4ec2a8a6da5535c3a5683a7fa;hb=bbaeadb068c3289c7df3b7bea0049f70a648ba00;hp=90aaf982ae019c5facbcf5fba54843914c5445b7;hpb=852c2ed260860b6b85c84f9fe96fb4d23d49c9f2;p=thirdparty%2Fopenssl.git diff --git a/apps/dgst.c b/apps/dgst.c index 90aaf982ae..fe05b312d7 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -21,12 +21,10 @@ #include #include -DEFINE_STACK_OF_STRING() - #undef BUFSIZE #define BUFSIZE 1024*8 -int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, +int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, const char *file); @@ -38,11 +36,12 @@ struct doall_dgst_digests { }; typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_LIST, + OPT_COMMON, + OPT_LIST, OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY, OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL, OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT, - OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, + OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN, OPT_DIGEST, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -64,9 +63,10 @@ const OPTIONS dgst_options[] = { {"c", OPT_C, '-', "Print the digest with separating colons"}, {"r", OPT_R, '-', "Print the digest in coreutils format"}, {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, - {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"}, + {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"}, {"hex", OPT_HEX, '-', "Print as hex dump"}, {"binary", OPT_BINARY, '-', "Print in binary form"}, + {"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"}, {"d", OPT_DEBUG, '-', "Print debug info"}, {"debug", OPT_DEBUG, '-', "Print debug info"}, @@ -98,23 +98,26 @@ int dgst_main(int argc, char **argv) EVP_PKEY *sigkey = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; char *hmac_key = NULL; - char *mac_name = NULL; + char *mac_name = NULL, *digestname = NULL; char *passinarg = NULL, *passin = NULL; - const EVP_MD *md = NULL, *m; + EVP_MD *md = NULL; const char *outfile = NULL, *keyfile = NULL, *prog = NULL; const char *sigfile = NULL; const char *md_name = NULL; OPTION_CHOICE o; - int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0; - int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0; + int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0; + int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0; + int xoflen = 0; unsigned char *buf = NULL, *sigbuf = NULL; int engine_impl = 0; struct doall_dgst_digests dec; - prog = opt_progname(argv[0]); buf = app_malloc(BUFSIZE, "I/O buffer"); - md = EVP_get_digestbyname(prog); + md = (EVP_MD *)EVP_get_digestbyname(argv[0]); + if (md != NULL) + digestname = argv[0]; + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, dgst_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -125,7 +128,7 @@ int dgst_main(int argc, char **argv) goto end; case OPT_HELP: opt_help(dgst_options); - ret = 0; + ret = EXIT_SUCCESS; goto end; case OPT_LIST: BIO_printf(bio_out, "Supported digests:\n"); @@ -134,7 +137,7 @@ int dgst_main(int argc, char **argv) OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, show_digests, &dec); BIO_printf(bio_out, "\n"); - ret = 0; + ret = EXIT_SUCCESS; goto end; case OPT_C: separator = 1; @@ -182,6 +185,9 @@ int dgst_main(int argc, char **argv) case OPT_BINARY: out_bin = 1; break; + case OPT_XOFLEN: + xoflen = atoi(opt_arg()); + break; case OPT_DEBUG: debug = 1; break; @@ -207,9 +213,7 @@ int dgst_main(int argc, char **argv) goto opthelp; break; case OPT_DIGEST: - if (!opt_md(opt_unknown(), &m)) - goto opthelp; - md = m; + digestname = opt_unknown(); break; case OPT_PROV_CASES: if (!opt_provider(o)) @@ -217,12 +221,21 @@ int dgst_main(int argc, char **argv) break; } } + + /* Remaining args are files to digest. */ argc = opt_num_rest(); argv = opt_rest(); if (keyfile != NULL && argc > 1) { BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog); goto end; } + if (!app_RAND_load()) + goto end; + + if (digestname != NULL) { + if (!opt_md(digestname, &md)) + goto opthelp; + } if (do_verify && sigfile == NULL) { BIO_printf(bio_err, @@ -234,13 +247,11 @@ int dgst_main(int argc, char **argv) in = BIO_new(BIO_s_file()); bmd = BIO_new(BIO_f_md()); - if ((in == NULL) || (bmd == NULL)) { - ERR_print_errors(bio_err); + if (in == NULL || bmd == NULL) goto end; - } if (debug) { - BIO_set_callback(in, BIO_debug_callback); + BIO_set_callback_ex(in, BIO_debug_callback_ex); /* needed for windows 3.1 */ BIO_set_callback_arg(in, (char *)bio_err); } @@ -262,7 +273,7 @@ int dgst_main(int argc, char **argv) goto end; if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) { - BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n"); + BIO_printf(bio_err, "MAC and signing key cannot both be specified\n"); goto end; } @@ -270,16 +281,16 @@ int dgst_main(int argc, char **argv) int type; if (want_pub) - sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file"); + sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key"); else - sigkey = load_key(keyfile, keyform, 0, passin, e, "key file"); + sigkey = load_key(keyfile, keyform, 0, passin, e, "private key"); if (sigkey == NULL) { /* * load_[pub]key() has already printed an appropriate message */ goto end; } - type = EVP_PKEY_id(sigkey); + type = EVP_PKEY_get_id(sigkey); if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) { /* * We implement PureEdDSA for these which doesn't have a separate @@ -292,36 +303,34 @@ int dgst_main(int argc, char **argv) if (mac_name != NULL) { EVP_PKEY_CTX *mac_ctx = NULL; - int r = 0; - if (!init_gen_str(&mac_ctx, mac_name, impl, 0)) - goto mac_end; + + if (!init_gen_str(&mac_ctx, mac_name, impl, 0, NULL, NULL)) + goto end; if (macopts != NULL) { - char *macopt; for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) { - macopt = sk_OPENSSL_STRING_value(macopts, i); + char *macopt = sk_OPENSSL_STRING_value(macopts, i); + if (pkey_ctrl_string(mac_ctx, macopt) <= 0) { - BIO_printf(bio_err, - "MAC parameter error \"%s\"\n", macopt); - ERR_print_errors(bio_err); - goto mac_end; + EVP_PKEY_CTX_free(mac_ctx); + BIO_printf(bio_err, "MAC parameter error \"%s\"\n", macopt); + goto end; } } } - if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) { - BIO_puts(bio_err, "Error generating key\n"); - ERR_print_errors(bio_err); - goto mac_end; - } - r = 1; - mac_end: + + sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */); + /* Verbose output would make external-tests gost-engine fail */ EVP_PKEY_CTX_free(mac_ctx); - if (r == 0) - goto end; } if (hmac_key != NULL) { + if (md == NULL) { + md = (EVP_MD *)EVP_sha256(); + digestname = SN_sha256; + } sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl, - (unsigned char *)hmac_key, -1); + (unsigned char *)hmac_key, + strlen(hmac_key)); if (sigkey == NULL) goto end; } @@ -329,28 +338,37 @@ int dgst_main(int argc, char **argv) if (sigkey != NULL) { EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; - int r; - if (!BIO_get_md_ctx(bmd, &mctx)) { + int res; + + if (BIO_get_md_ctx(bmd, &mctx) <= 0) { BIO_printf(bio_err, "Error getting context\n"); - ERR_print_errors(bio_err); goto end; } if (do_verify) - r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); + if (impl == NULL) + res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname, + app_get0_libctx(), + app_get0_propq(), sigkey, NULL); + else + res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); else - r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); - if (!r) { + if (impl == NULL) + res = EVP_DigestSignInit_ex(mctx, &pctx, digestname, + app_get0_libctx(), + app_get0_propq(), sigkey, NULL); + else + res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); + if (res == 0) { BIO_printf(bio_err, "Error setting context\n"); - ERR_print_errors(bio_err); goto end; } if (sigopts != NULL) { - char *sigopt; for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { - sigopt = sk_OPENSSL_STRING_value(sigopts, i); + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pctx, sigopt) <= 0) { - BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Signature parameter error \"%s\"\n", + sigopt); goto end; } } @@ -359,34 +377,31 @@ int dgst_main(int argc, char **argv) /* we use md as a filter, reading from 'in' */ else { EVP_MD_CTX *mctx = NULL; - if (!BIO_get_md_ctx(bmd, &mctx)) { + if (BIO_get_md_ctx(bmd, &mctx) <= 0) { BIO_printf(bio_err, "Error getting context\n"); - ERR_print_errors(bio_err); goto end; } if (md == NULL) - md = EVP_sha256(); + md = (EVP_MD *)EVP_sha256(); if (!EVP_DigestInit_ex(mctx, md, impl)) { BIO_printf(bio_err, "Error setting digest\n"); - ERR_print_errors(bio_err); goto end; } } if (sigfile != NULL && sigkey != NULL) { BIO *sigbio = BIO_new_file(sigfile, "rb"); + if (sigbio == NULL) { BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); - ERR_print_errors(bio_err); goto end; } - siglen = EVP_PKEY_size(sigkey); + siglen = EVP_PKEY_get_size(sigkey); sigbuf = app_malloc(siglen, "signature buffer"); siglen = BIO_read(sigbio, sigbuf, siglen); BIO_free(sigbio); if (siglen <= 0) { BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); - ERR_print_errors(bio_err); goto end; } } @@ -394,48 +409,62 @@ int dgst_main(int argc, char **argv) if (md == NULL) { EVP_MD_CTX *tctx; + BIO_get_md_ctx(bmd, &tctx); - md = EVP_MD_CTX_md(tctx); + md = EVP_MD_CTX_get1_md(tctx); } if (md != NULL) - md_name = EVP_MD_name(md); + md_name = EVP_MD_get0_name(md); + + if (xoflen > 0) { + if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) { + BIO_printf(bio_err, "Length can only be specified for XOF\n"); + goto end; + } + /* + * Signing using XOF is not supported by any algorithms currently since + * each algorithm only calls EVP_DigestFinal_ex() in their sign_final + * and verify_final methods. + */ + if (sigkey != NULL) { + BIO_printf(bio_err, "Signing key cannot be specified for XOF\n"); + goto end; + } + } if (argc == 0) { BIO_set_fp(in, stdin, BIO_NOCLOSE); - ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, + ret = do_fp(out, buf, inp, separator, out_bin, xoflen, sigkey, sigbuf, siglen, NULL, md_name, "stdin"); } else { const char *sig_name = NULL; - if (!out_bin) { - if (sigkey != NULL) { - const EVP_PKEY_ASN1_METHOD *ameth; - ameth = EVP_PKEY_get0_asn1(sigkey); - if (ameth) - EVP_PKEY_asn1_get0_info(NULL, NULL, - NULL, NULL, &sig_name, ameth); - } + + if (out_bin == 0) { + if (sigkey != NULL) + sig_name = EVP_PKEY_get0_type_name(sigkey); } - ret = 0; + ret = EXIT_SUCCESS; for (i = 0; i < argc; i++) { - int r; if (BIO_read_filename(in, argv[i]) <= 0) { perror(argv[i]); - ret++; + ret = EXIT_FAILURE; continue; } else { - r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, - siglen, sig_name, md_name, argv[i]); + if (do_fp(out, buf, inp, separator, out_bin, xoflen, + sigkey, sigbuf, siglen, sig_name, md_name, argv[i])) + ret = EXIT_FAILURE; } - if (r) - ret = r; (void)BIO_reset(bmd); } } end: + if (ret != EXIT_SUCCESS) + ERR_print_errors(bio_err); OPENSSL_clear_free(buf, BUFSIZE); BIO_free(in); OPENSSL_free(passin); BIO_free_all(out); + EVP_MD_free(md); EVP_PKEY_free(sigkey); sk_OPENSSL_STRING_free(sigopts); sk_OPENSSL_STRING_free(macopts); @@ -458,9 +487,12 @@ static void show_digests(const OBJ_NAME *name, void *arg) return; /* Filter out message digests that we cannot use */ - md = EVP_get_digestbyname(name->name); - if (md == NULL) - return; + md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq()); + if (md == NULL) { + md = EVP_get_digestbyname(name->name); + if (md == NULL) + return; + } BIO_printf(dec->bio, "-%-25s", name->name); if (++dec->n == 3) { @@ -481,7 +513,7 @@ static void show_digests(const OBJ_NAME *name, void *arg) * in the '*sum' checksum programs. This aims to preserve backward * compatibility. */ -static const char *newline_escape_filename(const char *file, int * backslash) +static const char *newline_escape_filename(const char *file, int *backslash) { size_t i, e = 0, length = strlen(file), newline_count = 0, mem_len = 0; char *file_cpy = NULL; @@ -494,7 +526,7 @@ static const char *newline_escape_filename(const char *file, int * backslash) file_cpy = app_malloc(mem_len, file); i = 0; - while(e < length) { + while (e < length) { const char c = file[e]; if (c == '\n') { file_cpy[i++] = '\\'; @@ -510,20 +542,19 @@ static const char *newline_escape_filename(const char *file, int * backslash) } -int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, +int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *sig_name, const char *md_name, const char *file) { size_t len = BUFSIZE; - int i, backslash = 0, ret = 1; - unsigned char *sigbuf = NULL; + int i, backslash = 0, ret = EXIT_FAILURE; + unsigned char *allocated_buf = NULL; while (BIO_pending(bp) || !BIO_eof(bp)) { i = BIO_read(bp, (char *)buf, BUFSIZE); if (i < 0) { - BIO_printf(bio_err, "Read Error in %s\n", file); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Read error in %s\n", file); goto end; } if (i == 0) @@ -536,14 +567,13 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, if (i > 0) { BIO_printf(out, "Verified OK\n"); } else if (i == 0) { - BIO_printf(out, "Verification Failure\n"); + BIO_printf(out, "Verification failure\n"); goto end; } else { - BIO_printf(bio_err, "Error Verifying Data\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error verifying data\n"); goto end; } - ret = 0; + ret = EXIT_SUCCESS; goto end; } if (key != NULL) { @@ -552,26 +582,37 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, BIO_get_md_ctx(bp, &ctx); if (!EVP_DigestSignFinal(ctx, NULL, &tmplen)) { - BIO_printf(bio_err, "Error Signing Data\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error getting maximum length of signed data\n"); goto end; } if (tmplen > BUFSIZE) { len = tmplen; - sigbuf = app_malloc(len, "Signature buffer"); - buf = sigbuf; + allocated_buf = app_malloc(len, "Signature buffer"); + buf = allocated_buf; } if (!EVP_DigestSignFinal(ctx, buf, &len)) { - BIO_printf(bio_err, "Error Signing Data\n"); - ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error signing data\n"); + goto end; + } + } else if (xoflen > 0) { + EVP_MD_CTX *ctx; + + len = xoflen; + if (len > BUFSIZE) { + allocated_buf = app_malloc(len, "Digest buffer"); + buf = allocated_buf; + } + + BIO_get_md_ctx(bp, &ctx); + + if (!EVP_DigestFinalXOF(ctx, buf, len)) { + BIO_printf(bio_err, "Error Digesting Data\n"); goto end; } } else { len = BIO_gets(bp, (char *)buf, BUFSIZE); - if ((int)len < 0) { - ERR_print_errors(bio_err); + if ((int)len < 0) goto end; - } } if (binout) { @@ -606,10 +647,10 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, BIO_printf(out, "\n"); } - ret = 0; + ret = EXIT_SUCCESS; end: - if (sigbuf != NULL) - OPENSSL_clear_free(sigbuf, len); + if (allocated_buf != NULL) + OPENSSL_clear_free(allocated_buf, len); return ret; }