dgst.c revision 296465
1/* apps/dgst.c */ 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 <string.h> 61#include <stdlib.h> 62#include "apps.h" 63#include <openssl/bio.h> 64#include <openssl/err.h> 65#include <openssl/evp.h> 66#include <openssl/objects.h> 67#include <openssl/x509.h> 68#include <openssl/pem.h> 69#include <openssl/hmac.h> 70 71#undef BUFSIZE 72#define BUFSIZE 1024*8 73 74#undef PROG 75#define PROG dgst_main 76 77int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, 78 EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title, 79 const char *file, BIO *bmd, const char *hmac_key, 80 int non_fips_allow); 81 82int MAIN(int, char **); 83 84int MAIN(int argc, char **argv) 85{ 86 ENGINE *e = NULL; 87 unsigned char *buf = NULL; 88 int i, err = 1; 89 const EVP_MD *md = NULL, *m; 90 BIO *in = NULL, *inp; 91 BIO *bmd = NULL; 92 BIO *out = NULL; 93 const char *name; 94#define PROG_NAME_SIZE 39 95 char pname[PROG_NAME_SIZE + 1]; 96 int separator = 0; 97 int debug = 0; 98 int keyform = FORMAT_PEM; 99 const char *outfile = NULL, *keyfile = NULL; 100 const char *sigfile = NULL, *randfile = NULL; 101 int out_bin = -1, want_pub = 0, do_verify = 0; 102 EVP_PKEY *sigkey = NULL; 103 unsigned char *sigbuf = NULL; 104 int siglen = 0; 105 unsigned int sig_flags = 0; 106 char *passargin = NULL, *passin = NULL; 107#ifndef OPENSSL_NO_ENGINE 108 char *engine = NULL; 109#endif 110 char *hmac_key = NULL; 111 int non_fips_allow = 0; 112 113 apps_startup(); 114 ERR_load_crypto_strings(); 115 if ((buf = (unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL) { 116 BIO_printf(bio_err, "out of memory\n"); 117 goto end; 118 } 119 if (bio_err == NULL) 120 if ((bio_err = BIO_new(BIO_s_file())) != NULL) 121 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 122 123 if (!load_config(bio_err, NULL)) 124 goto end; 125 126 /* first check the program name */ 127 program_name(argv[0], pname, sizeof pname); 128 129 md = EVP_get_digestbyname(pname); 130 131 argc--; 132 argv++; 133 while (argc > 0) { 134 if ((*argv)[0] != '-') 135 break; 136 if (strcmp(*argv, "-c") == 0) 137 separator = 1; 138 else if (strcmp(*argv, "-rand") == 0) { 139 if (--argc < 1) 140 break; 141 randfile = *(++argv); 142 } else if (strcmp(*argv, "-out") == 0) { 143 if (--argc < 1) 144 break; 145 outfile = *(++argv); 146 } else if (strcmp(*argv, "-sign") == 0) { 147 if (--argc < 1) 148 break; 149 keyfile = *(++argv); 150 } else if (!strcmp(*argv, "-passin")) { 151 if (--argc < 1) 152 break; 153 passargin = *++argv; 154 } else if (strcmp(*argv, "-verify") == 0) { 155 if (--argc < 1) 156 break; 157 keyfile = *(++argv); 158 want_pub = 1; 159 do_verify = 1; 160 } else if (strcmp(*argv, "-prverify") == 0) { 161 if (--argc < 1) 162 break; 163 keyfile = *(++argv); 164 do_verify = 1; 165 } else if (strcmp(*argv, "-x931") == 0) 166 sig_flags = EVP_MD_CTX_FLAG_PAD_X931; 167 else if (strcmp(*argv, "-pss_saltlen") == 0) { 168 int saltlen; 169 if (--argc < 1) 170 break; 171 saltlen = atoi(*(++argv)); 172 if (saltlen == -1) 173 sig_flags = EVP_MD_CTX_FLAG_PSS_MREC; 174 else if (saltlen == -2) 175 sig_flags = EVP_MD_CTX_FLAG_PSS_MDLEN; 176 else if (saltlen < -2 || saltlen >= 0xFFFE) { 177 BIO_printf(bio_err, "Invalid PSS salt length %d\n", saltlen); 178 goto end; 179 } else 180 sig_flags = saltlen; 181 sig_flags <<= 16; 182 sig_flags |= EVP_MD_CTX_FLAG_PAD_PSS; 183 } else if (strcmp(*argv, "-signature") == 0) { 184 if (--argc < 1) 185 break; 186 sigfile = *(++argv); 187 } else if (strcmp(*argv, "-keyform") == 0) { 188 if (--argc < 1) 189 break; 190 keyform = str2fmt(*(++argv)); 191 } 192#ifndef OPENSSL_NO_ENGINE 193 else if (strcmp(*argv, "-engine") == 0) { 194 if (--argc < 1) 195 break; 196 engine = *(++argv); 197 } 198#endif 199 else if (strcmp(*argv, "-hex") == 0) 200 out_bin = 0; 201 else if (strcmp(*argv, "-binary") == 0) 202 out_bin = 1; 203 else if (strcmp(*argv, "-d") == 0) 204 debug = 1; 205 else if (strcmp(*argv, "-non-fips-allow") == 0) 206 non_fips_allow = 1; 207 else if (!strcmp(*argv, "-fips-fingerprint")) 208 hmac_key = "etaonrishdlcupfm"; 209 else if (!strcmp(*argv, "-hmac")) { 210 if (--argc < 1) 211 break; 212 hmac_key = *++argv; 213 } else if ((m = EVP_get_digestbyname(&((*argv)[1]))) != NULL) 214 md = m; 215 else 216 break; 217 argc--; 218 argv++; 219 } 220 221 if (md == NULL) 222 md = EVP_md5(); 223 224 if (do_verify && !sigfile) { 225 BIO_printf(bio_err, 226 "No signature to verify: use the -signature option\n"); 227 err = 1; 228 goto end; 229 } 230 231 if ((argc > 0) && (argv[0][0] == '-')) { /* bad option */ 232 BIO_printf(bio_err, "unknown option '%s'\n", *argv); 233 BIO_printf(bio_err, "options are\n"); 234 BIO_printf(bio_err, 235 "-c to output the digest with separating colons\n"); 236 BIO_printf(bio_err, "-d to output debug info\n"); 237 BIO_printf(bio_err, "-hex output as hex dump\n"); 238 BIO_printf(bio_err, "-binary output in binary form\n"); 239 BIO_printf(bio_err, 240 "-sign file sign digest using private key in file\n"); 241 BIO_printf(bio_err, 242 "-verify file verify a signature using public key in file\n"); 243 BIO_printf(bio_err, 244 "-prverify file verify a signature using private key in file\n"); 245 BIO_printf(bio_err, 246 "-keyform arg key file format (PEM or ENGINE)\n"); 247 BIO_printf(bio_err, "-signature file signature to verify\n"); 248 BIO_printf(bio_err, "-binary output in binary form\n"); 249 BIO_printf(bio_err, "-hmac key create hashed MAC with key\n"); 250#ifndef OPENSSL_NO_ENGINE 251 BIO_printf(bio_err, 252 "-engine e use engine e, possibly a hardware device.\n"); 253#endif 254 255 BIO_printf(bio_err, 256 "-%-14s to use the %s message digest algorithm (default)\n", 257 LN_md5, LN_md5); 258 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 259 LN_md4, LN_md4); 260 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 261 LN_md2, LN_md2); 262#ifndef OPENSSL_NO_SHA 263 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 264 LN_sha1, LN_sha1); 265 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 266 LN_sha, LN_sha); 267# ifndef OPENSSL_NO_SHA256 268 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 269 LN_sha224, LN_sha224); 270 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 271 LN_sha256, LN_sha256); 272# endif 273# ifndef OPENSSL_NO_SHA512 274 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 275 LN_sha384, LN_sha384); 276 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 277 LN_sha512, LN_sha512); 278# endif 279#endif 280 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 281 LN_mdc2, LN_mdc2); 282 BIO_printf(bio_err, "-%-14s to use the %s message digest algorithm\n", 283 LN_ripemd160, LN_ripemd160); 284 err = 1; 285 goto end; 286 } 287#ifndef OPENSSL_NO_ENGINE 288 e = setup_engine(bio_err, engine, 0); 289#endif 290 291 in = BIO_new(BIO_s_file()); 292 bmd = BIO_new(BIO_f_md()); 293 if (debug) { 294 BIO_set_callback(in, BIO_debug_callback); 295 /* needed for windows 3.1 */ 296 BIO_set_callback_arg(in, (char *)bio_err); 297 } 298 299 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 300 BIO_printf(bio_err, "Error getting password\n"); 301 goto end; 302 } 303 304 if ((in == NULL) || (bmd == NULL)) { 305 ERR_print_errors(bio_err); 306 goto end; 307 } 308 309 if (out_bin == -1) { 310 if (keyfile) 311 out_bin = 1; 312 else 313 out_bin = 0; 314 } 315 316 if (randfile) 317 app_RAND_load_file(randfile, bio_err, 0); 318 319 if (outfile) { 320 if (out_bin) 321 out = BIO_new_file(outfile, "wb"); 322 else 323 out = BIO_new_file(outfile, "w"); 324 } else { 325 out = BIO_new_fp(stdout, BIO_NOCLOSE); 326#ifdef OPENSSL_SYS_VMS 327 { 328 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 329 out = BIO_push(tmpbio, out); 330 } 331#endif 332 } 333 334 if (!out) { 335 BIO_printf(bio_err, "Error opening output file %s\n", 336 outfile ? outfile : "(stdout)"); 337 ERR_print_errors(bio_err); 338 goto end; 339 } 340 341 if (keyfile) { 342 if (want_pub) 343 sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, 344 e, "key file"); 345 else 346 sigkey = load_key(bio_err, keyfile, keyform, 0, passin, 347 e, "key file"); 348 if (!sigkey) { 349 /* 350 * load_[pub]key() has already printed an appropriate message 351 */ 352 goto end; 353 } 354 } 355 356 if (sigfile && sigkey) { 357 BIO *sigbio; 358 sigbio = BIO_new_file(sigfile, "rb"); 359 siglen = EVP_PKEY_size(sigkey); 360 sigbuf = OPENSSL_malloc(siglen); 361 if (!sigbio) { 362 BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); 363 ERR_print_errors(bio_err); 364 goto end; 365 } 366 siglen = BIO_read(sigbio, sigbuf, siglen); 367 BIO_free(sigbio); 368 if (siglen <= 0) { 369 BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); 370 ERR_print_errors(bio_err); 371 goto end; 372 } 373 } 374 375 if (non_fips_allow) { 376 EVP_MD_CTX *md_ctx; 377 BIO_get_md_ctx(bmd, &md_ctx); 378 EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 379 } 380 381 if (sig_flags) { 382 EVP_MD_CTX *md_ctx; 383 BIO_get_md_ctx(bmd, &md_ctx); 384 EVP_MD_CTX_set_flags(md_ctx, sig_flags); 385 } 386 387 /* we use md as a filter, reading from 'in' */ 388 if (!BIO_set_md(bmd, md)) { 389 BIO_printf(bio_err, "Error setting digest %s\n", pname); 390 ERR_print_errors(bio_err); 391 goto end; 392 } 393 394 inp = BIO_push(bmd, in); 395 396 if (argc == 0) { 397 BIO_set_fp(in, stdin, BIO_NOCLOSE); 398 err = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, 399 siglen, "", "(stdin)", bmd, hmac_key, non_fips_allow); 400 } else { 401 name = OBJ_nid2sn(md->type); 402 err = 0; 403 for (i = 0; i < argc; i++) { 404 char *tmp, *tofree = NULL; 405 int r; 406 407 if (BIO_read_filename(in, argv[i]) <= 0) { 408 perror(argv[i]); 409 err++; 410 continue; 411 } 412 if (!out_bin) { 413 size_t len = 414 strlen(name) + strlen(argv[i]) + (hmac_key ? 5 : 0) + 5; 415 tmp = tofree = OPENSSL_malloc(len); 416 BIO_snprintf(tmp, len, "%s%s(%s)= ", 417 hmac_key ? "HMAC-" : "", name, argv[i]); 418 } else 419 tmp = ""; 420 r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf, 421 siglen, tmp, argv[i], bmd, hmac_key, non_fips_allow); 422 if (r) 423 err = r; 424 if (tofree) 425 OPENSSL_free(tofree); 426 (void)BIO_reset(bmd); 427 } 428 } 429 end: 430 if (buf != NULL) { 431 OPENSSL_cleanse(buf, BUFSIZE); 432 OPENSSL_free(buf); 433 } 434 if (in != NULL) 435 BIO_free(in); 436 if (passin) 437 OPENSSL_free(passin); 438 BIO_free_all(out); 439 EVP_PKEY_free(sigkey); 440 if (sigbuf) 441 OPENSSL_free(sigbuf); 442 if (bmd != NULL) 443 BIO_free(bmd); 444 apps_shutdown(); 445 OPENSSL_EXIT(err); 446} 447 448int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, 449 EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title, 450 const char *file, BIO *bmd, const char *hmac_key, 451 int non_fips_allow) 452{ 453 unsigned int len; 454 int i; 455 EVP_MD_CTX *md_ctx; 456 HMAC_CTX hmac_ctx; 457 458 if (hmac_key) { 459 EVP_MD *md; 460 461 BIO_get_md(bmd, &md); 462 HMAC_CTX_init(&hmac_ctx); 463 HMAC_Init_ex(&hmac_ctx, hmac_key, strlen(hmac_key), md, NULL); 464 BIO_get_md_ctx(bmd, &md_ctx); 465 BIO_set_md_ctx(bmd, &hmac_ctx.md_ctx); 466 } 467 for (;;) { 468 i = BIO_read(bp, (char *)buf, BUFSIZE); 469 if (i < 0) { 470 BIO_printf(bio_err, "Read Error in %s\n", file); 471 ERR_print_errors(bio_err); 472 return 1; 473 } 474 if (i == 0) 475 break; 476 } 477 if (sigin) { 478 EVP_MD_CTX *ctx; 479 BIO_get_md_ctx(bp, &ctx); 480 i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key); 481 if (i > 0) 482 BIO_printf(out, "Verified OK\n"); 483 else if (i == 0) { 484 BIO_printf(out, "Verification Failure\n"); 485 return 1; 486 } else { 487 BIO_printf(bio_err, "Error Verifying Data\n"); 488 ERR_print_errors(bio_err); 489 return 1; 490 } 491 return 0; 492 } 493 if (key) { 494 EVP_MD_CTX *ctx; 495 BIO_get_md_ctx(bp, &ctx); 496 if (!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key)) { 497 BIO_printf(bio_err, "Error Signing Data\n"); 498 ERR_print_errors(bio_err); 499 return 1; 500 } 501 } else if (hmac_key) { 502 HMAC_Final(&hmac_ctx, buf, &len); 503 HMAC_CTX_cleanup(&hmac_ctx); 504 } else 505 len = BIO_gets(bp, (char *)buf, BUFSIZE); 506 507 if (binout) 508 BIO_write(out, buf, len); 509 else { 510 BIO_write(out, title, strlen(title)); 511 for (i = 0; i < (int)len; i++) { 512 if (sep && (i != 0)) 513 BIO_printf(out, ":"); 514 BIO_printf(out, "%02x", buf[i]); 515 } 516 BIO_printf(out, "\n"); 517 } 518 if (hmac_key) { 519 BIO_set_md_ctx(bmd, md_ctx); 520 } 521 return 0; 522} 523