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