1 /* $OpenBSD: enc.c,v 1.31 2023/07/29 17:15:45 tb 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 #include <unistd.h> 63 64 #include "apps.h" 65 66 #include <openssl/bio.h> 67 #include <openssl/err.h> 68 #include <openssl/evp.h> 69 #include <openssl/objects.h> 70 71 int set_hex(char *in, unsigned char *out, int size); 72 73 #define SIZE (512) 74 #define BSIZE (8*1024) 75 76 static struct { 77 int base64; 78 char *bufsize; 79 const EVP_CIPHER *cipher; 80 int debug; 81 int enc; 82 char *hiv; 83 char *hkey; 84 char *hsalt; 85 char *inf; 86 int iter; 87 char *keyfile; 88 char *keystr; 89 char *md; 90 int nopad; 91 int nosalt; 92 int olb64; 93 char *outf; 94 char *passarg; 95 int pbkdf2; 96 int printkey; 97 int verbose; 98 } cfg; 99 100 static int 101 enc_opt_cipher(int argc, char **argv, int *argsused) 102 { 103 char *name = argv[0]; 104 105 if (*name++ != '-') 106 return (1); 107 108 if (strcmp(name, "none") == 0) { 109 cfg.cipher = NULL; 110 *argsused = 1; 111 return (0); 112 } 113 114 if ((cfg.cipher = EVP_get_cipherbyname(name)) != NULL) { 115 *argsused = 1; 116 return (0); 117 } 118 119 return (1); 120 } 121 122 static const struct option enc_options[] = { 123 { 124 .name = "A", 125 .desc = "Process base64 data on one line (requires -a)", 126 .type = OPTION_FLAG, 127 .opt.flag = &cfg.olb64, 128 }, 129 { 130 .name = "a", 131 .desc = "Perform base64 encoding/decoding (alias -base64)", 132 .type = OPTION_FLAG, 133 .opt.flag = &cfg.base64, 134 }, 135 { 136 .name = "base64", 137 .type = OPTION_FLAG, 138 .opt.flag = &cfg.base64, 139 }, 140 { 141 .name = "bufsize", 142 .argname = "size", 143 .desc = "Specify the buffer size to use for I/O", 144 .type = OPTION_ARG, 145 .opt.arg = &cfg.bufsize, 146 }, 147 { 148 .name = "d", 149 .desc = "Decrypt the input data", 150 .type = OPTION_VALUE, 151 .opt.value = &cfg.enc, 152 .value = 0, 153 }, 154 { 155 .name = "debug", 156 .desc = "Print debugging information", 157 .type = OPTION_FLAG, 158 .opt.flag = &cfg.debug, 159 }, 160 { 161 .name = "e", 162 .desc = "Encrypt the input data (default)", 163 .type = OPTION_VALUE, 164 .opt.value = &cfg.enc, 165 .value = 1, 166 }, 167 { 168 .name = "in", 169 .argname = "file", 170 .desc = "Input file to read from (default stdin)", 171 .type = OPTION_ARG, 172 .opt.arg = &cfg.inf, 173 }, 174 { 175 .name = "iter", 176 .argname = "iterations", 177 .desc = "Specify iteration count and force use of PBKDF2", 178 .type = OPTION_ARG_INT, 179 .opt.value = &cfg.iter, 180 }, 181 { 182 .name = "iv", 183 .argname = "IV", 184 .desc = "IV to use, specified as a hexadecimal string", 185 .type = OPTION_ARG, 186 .opt.arg = &cfg.hiv, 187 }, 188 { 189 .name = "K", 190 .argname = "key", 191 .desc = "Key to use, specified as a hexadecimal string", 192 .type = OPTION_ARG, 193 .opt.arg = &cfg.hkey, 194 }, 195 { 196 .name = "k", /* Superseded by -pass. */ 197 .type = OPTION_ARG, 198 .opt.arg = &cfg.keystr, 199 }, 200 { 201 .name = "kfile", /* Superseded by -pass. */ 202 .type = OPTION_ARG, 203 .opt.arg = &cfg.keyfile, 204 }, 205 { 206 .name = "md", 207 .argname = "digest", 208 .desc = "Digest to use to create a key from the passphrase", 209 .type = OPTION_ARG, 210 .opt.arg = &cfg.md, 211 }, 212 { 213 .name = "none", 214 .desc = "Use NULL cipher (no encryption or decryption)", 215 .type = OPTION_ARGV_FUNC, 216 .opt.argvfunc = enc_opt_cipher, 217 }, 218 { 219 .name = "nopad", 220 .desc = "Disable standard block padding", 221 .type = OPTION_FLAG, 222 .opt.flag = &cfg.nopad, 223 }, 224 { 225 .name = "nosalt", 226 .type = OPTION_VALUE, 227 .opt.value = &cfg.nosalt, 228 .value = 1, 229 }, 230 { 231 .name = "out", 232 .argname = "file", 233 .desc = "Output file to write to (default stdout)", 234 .type = OPTION_ARG, 235 .opt.arg = &cfg.outf, 236 }, 237 { 238 .name = "P", 239 .desc = "Print out the salt, key and IV used, then exit\n" 240 " (no encryption or decryption is performed)", 241 .type = OPTION_VALUE, 242 .opt.value = &cfg.printkey, 243 .value = 2, 244 }, 245 { 246 .name = "p", 247 .desc = "Print out the salt, key and IV used", 248 .type = OPTION_VALUE, 249 .opt.value = &cfg.printkey, 250 .value = 1, 251 }, 252 { 253 .name = "pass", 254 .argname = "source", 255 .desc = "Password source", 256 .type = OPTION_ARG, 257 .opt.arg = &cfg.passarg, 258 }, 259 { 260 .name = "pbkdf2", 261 .desc = "Use the pbkdf2 key derivation function", 262 .type = OPTION_FLAG, 263 .opt.flag = &cfg.pbkdf2, 264 }, 265 { 266 .name = "S", 267 .argname = "salt", 268 .desc = "Salt to use, specified as a hexadecimal string", 269 .type = OPTION_ARG, 270 .opt.arg = &cfg.hsalt, 271 }, 272 { 273 .name = "salt", 274 .desc = "Use a salt in the key derivation routines (default)", 275 .type = OPTION_VALUE, 276 .opt.value = &cfg.nosalt, 277 .value = 0, 278 }, 279 { 280 .name = "v", 281 .desc = "Verbose", 282 .type = OPTION_FLAG, 283 .opt.flag = &cfg.verbose, 284 }, 285 { 286 .name = NULL, 287 .type = OPTION_ARGV_FUNC, 288 .opt.argvfunc = enc_opt_cipher, 289 }, 290 { NULL }, 291 }; 292 293 static void 294 skip_aead_and_xts(const OBJ_NAME *name, void *arg) 295 { 296 const EVP_CIPHER *cipher; 297 298 if ((cipher = EVP_get_cipherbyname(name->name)) == NULL) 299 return; 300 301 if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) 302 return; 303 if (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) 304 return; 305 306 show_cipher(name, arg); 307 } 308 309 static void 310 enc_usage(void) 311 { 312 int n = 0; 313 314 fprintf(stderr, "usage: enc -ciphername [-AadePp] [-base64] " 315 "[-bufsize number] [-debug]\n" 316 " [-in file] [-iter iterations] [-iv IV] [-K key] " 317 "[-k password]\n" 318 " [-kfile file] [-md digest] [-none] [-nopad] [-nosalt]\n" 319 " [-out file] [-pass source] [-pbkdf2] [-S salt] [-salt]\n\n"); 320 options_usage(enc_options); 321 fprintf(stderr, "\n"); 322 323 fprintf(stderr, "Valid ciphername values:\n\n"); 324 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, skip_aead_and_xts, &n); 325 fprintf(stderr, "\n"); 326 } 327 328 int 329 enc_main(int argc, char **argv) 330 { 331 static const char magic[] = "Salted__"; 332 char mbuf[sizeof magic - 1]; 333 char *strbuf = NULL, *pass = NULL; 334 unsigned char *buff = NULL; 335 int bsize = BSIZE; 336 int ret = 1, inl; 337 unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; 338 unsigned char salt[PKCS5_SALT_LEN]; 339 EVP_CIPHER_CTX *ctx = NULL; 340 const EVP_MD *dgst = NULL; 341 BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL; 342 BIO *rbio = NULL, *wbio = NULL; 343 #define PROG_NAME_SIZE 39 344 char pname[PROG_NAME_SIZE + 1]; 345 int i; 346 347 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { 348 perror("pledge"); 349 exit(1); 350 } 351 352 memset(&cfg, 0, sizeof(cfg)); 353 cfg.enc = 1; 354 355 /* first check the program name */ 356 program_name(argv[0], pname, sizeof(pname)); 357 358 if (strcmp(pname, "base64") == 0) 359 cfg.base64 = 1; 360 361 cfg.cipher = EVP_get_cipherbyname(pname); 362 363 if (!cfg.base64 && cfg.cipher == NULL && strcmp(pname, "enc") != 0) { 364 BIO_printf(bio_err, "%s is an unknown cipher\n", pname); 365 goto end; 366 } 367 368 if (options_parse(argc, argv, enc_options, NULL, NULL) != 0) { 369 enc_usage(); 370 goto end; 371 } 372 373 if (cfg.keyfile != NULL) { 374 static char buf[128]; 375 FILE *infile; 376 377 infile = fopen(cfg.keyfile, "r"); 378 if (infile == NULL) { 379 BIO_printf(bio_err, "unable to read key from '%s'\n", 380 cfg.keyfile); 381 goto end; 382 } 383 buf[0] = '\0'; 384 if (!fgets(buf, sizeof buf, infile)) { 385 BIO_printf(bio_err, "unable to read key from '%s'\n", 386 cfg.keyfile); 387 fclose(infile); 388 goto end; 389 } 390 fclose(infile); 391 i = strlen(buf); 392 if (i > 0 && (buf[i - 1] == '\n' || buf[i - 1] == '\r')) 393 buf[--i] = '\0'; 394 if (i > 0 && (buf[i - 1] == '\n' || buf[i - 1] == '\r')) 395 buf[--i] = '\0'; 396 if (i < 1) { 397 BIO_printf(bio_err, "zero length password\n"); 398 goto end; 399 } 400 cfg.keystr = buf; 401 } 402 403 if (cfg.cipher != NULL && 404 (EVP_CIPHER_flags(cfg.cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { 405 BIO_printf(bio_err, "enc does not support AEAD ciphers\n"); 406 goto end; 407 } 408 409 if (cfg.cipher != NULL && 410 EVP_CIPHER_mode(cfg.cipher) == EVP_CIPH_XTS_MODE) { 411 BIO_printf(bio_err, "enc does not support XTS mode\n"); 412 goto end; 413 } 414 415 if (cfg.md != NULL && 416 (dgst = EVP_get_digestbyname(cfg.md)) == NULL) { 417 BIO_printf(bio_err, 418 "%s is an unsupported message digest type\n", 419 cfg.md); 420 goto end; 421 } 422 if (dgst == NULL) 423 dgst = EVP_sha256(); 424 425 if (cfg.bufsize != NULL) { 426 char *p = cfg.bufsize; 427 unsigned long n; 428 429 /* XXX - provide an OPTION_ARG_DISKUNIT. */ 430 for (n = 0; *p != '\0'; p++) { 431 i = *p; 432 if ((i <= '9') && (i >= '0')) 433 n = n * 10 + i - '0'; 434 else if (i == 'k') { 435 n *= 1024; 436 p++; 437 break; 438 } 439 } 440 if (*p != '\0') { 441 BIO_printf(bio_err, "invalid 'bufsize' specified.\n"); 442 goto end; 443 } 444 /* It must be large enough for a base64 encoded line. */ 445 if (cfg.base64 && n < 80) 446 n = 80; 447 448 bsize = (int)n; 449 if (cfg.verbose) 450 BIO_printf(bio_err, "bufsize=%d\n", bsize); 451 } 452 strbuf = malloc(SIZE); 453 buff = malloc(EVP_ENCODE_LENGTH(bsize)); 454 if (buff == NULL || strbuf == NULL) { 455 BIO_printf(bio_err, "malloc failure %ld\n", (long) EVP_ENCODE_LENGTH(bsize)); 456 goto end; 457 } 458 in = BIO_new(BIO_s_file()); 459 out = BIO_new(BIO_s_file()); 460 if (in == NULL || out == NULL) { 461 ERR_print_errors(bio_err); 462 goto end; 463 } 464 if (cfg.debug) { 465 BIO_set_callback(in, BIO_debug_callback); 466 BIO_set_callback(out, BIO_debug_callback); 467 BIO_set_callback_arg(in, (char *) bio_err); 468 BIO_set_callback_arg(out, (char *) bio_err); 469 } 470 if (cfg.inf == NULL) { 471 if (cfg.bufsize != NULL) 472 setvbuf(stdin, (char *) NULL, _IONBF, 0); 473 BIO_set_fp(in, stdin, BIO_NOCLOSE); 474 } else { 475 if (BIO_read_filename(in, cfg.inf) <= 0) { 476 perror(cfg.inf); 477 goto end; 478 } 479 } 480 481 if (!cfg.keystr && cfg.passarg) { 482 if (!app_passwd(bio_err, cfg.passarg, NULL, &pass, NULL)) { 483 BIO_printf(bio_err, "Error getting password\n"); 484 goto end; 485 } 486 cfg.keystr = pass; 487 } 488 if (cfg.keystr == NULL && cfg.cipher != NULL && cfg.hkey == NULL) { 489 for (;;) { 490 char buf[200]; 491 int retval; 492 493 retval = snprintf(buf, sizeof buf, 494 "enter %s %s password:", 495 OBJ_nid2ln(EVP_CIPHER_nid(cfg.cipher)), 496 cfg.enc ? "encryption" : "decryption"); 497 if ((size_t)retval >= sizeof buf) { 498 BIO_printf(bio_err, 499 "Password prompt too long\n"); 500 goto end; 501 } 502 strbuf[0] = '\0'; 503 i = EVP_read_pw_string((char *)strbuf, SIZE, buf, 504 cfg.enc); 505 if (i == 0) { 506 if (strbuf[0] == '\0') { 507 ret = 1; 508 goto end; 509 } 510 cfg.keystr = strbuf; 511 break; 512 } 513 if (i < 0) { 514 BIO_printf(bio_err, "bad password read\n"); 515 goto end; 516 } 517 } 518 } 519 if (cfg.outf == NULL) { 520 BIO_set_fp(out, stdout, BIO_NOCLOSE); 521 if (cfg.bufsize != NULL) 522 setvbuf(stdout, (char *)NULL, _IONBF, 0); 523 } else { 524 if (BIO_write_filename(out, cfg.outf) <= 0) { 525 perror(cfg.outf); 526 goto end; 527 } 528 } 529 530 rbio = in; 531 wbio = out; 532 533 if (cfg.base64) { 534 if ((b64 = BIO_new(BIO_f_base64())) == NULL) 535 goto end; 536 if (cfg.debug) { 537 BIO_set_callback(b64, BIO_debug_callback); 538 BIO_set_callback_arg(b64, (char *) bio_err); 539 } 540 if (cfg.olb64) 541 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); 542 if (cfg.enc) 543 wbio = BIO_push(b64, wbio); 544 else 545 rbio = BIO_push(b64, rbio); 546 } 547 if (cfg.cipher != NULL) { 548 /* 549 * Note that keystr is NULL if a key was passed on the command 550 * line, so we get no salt in that case. Is this a bug? 551 */ 552 if (cfg.keystr != NULL) { 553 /* 554 * Salt handling: if encrypting generate a salt and 555 * write to output BIO. If decrypting read salt from 556 * input BIO. 557 */ 558 unsigned char *sptr; 559 if (cfg.nosalt) 560 sptr = NULL; 561 else { 562 if (cfg.enc) { 563 if (cfg.hsalt) { 564 if (!set_hex(cfg.hsalt, salt, sizeof salt)) { 565 BIO_printf(bio_err, 566 "invalid hex salt value\n"); 567 goto end; 568 } 569 } else 570 arc4random_buf(salt, 571 sizeof(salt)); 572 /* 573 * If -P option then don't bother 574 * writing 575 */ 576 if ((cfg.printkey != 2) 577 && (BIO_write(wbio, magic, 578 sizeof magic - 1) != sizeof magic - 1 579 || BIO_write(wbio, 580 (char *) salt, 581 sizeof salt) != sizeof salt)) { 582 BIO_printf(bio_err, "error writing output file\n"); 583 goto end; 584 } 585 } else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf 586 || BIO_read(rbio, 587 (unsigned char *) salt, 588 sizeof salt) != sizeof salt) { 589 BIO_printf(bio_err, "error reading input file\n"); 590 goto end; 591 } else if (memcmp(mbuf, magic, sizeof magic - 1)) { 592 BIO_printf(bio_err, "bad magic number\n"); 593 goto end; 594 } 595 sptr = salt; 596 } 597 if (cfg.pbkdf2 == 1 || cfg.iter > 0) { 598 /* 599 * derive key and default iv 600 * concatenated into a temporary buffer 601 */ 602 unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH]; 603 int iklen = EVP_CIPHER_key_length(cfg.cipher); 604 int ivlen = EVP_CIPHER_iv_length(cfg.cipher); 605 /* not needed if HASH_UPDATE() is fixed : */ 606 int islen = (sptr != NULL ? sizeof(salt) : 0); 607 608 if (cfg.iter == 0) 609 cfg.iter = 10000; 610 611 if (!PKCS5_PBKDF2_HMAC(cfg.keystr, 612 strlen(cfg.keystr), sptr, islen, 613 cfg.iter, dgst, iklen+ivlen, tmpkeyiv)) { 614 BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n"); 615 goto end; 616 } 617 /* split and move data back to global buffer */ 618 memcpy(key, tmpkeyiv, iklen); 619 memcpy(iv, tmpkeyiv + iklen, ivlen); 620 explicit_bzero(tmpkeyiv, sizeof tmpkeyiv); 621 } else { 622 EVP_BytesToKey(cfg.cipher, dgst, sptr, 623 (unsigned char *)cfg.keystr, 624 strlen(cfg.keystr), 1, key, iv); 625 } 626 627 /* 628 * zero the complete buffer or the string passed from 629 * the command line bug picked up by Larry J. Hughes 630 * Jr. <hughes@indiana.edu> 631 */ 632 if (cfg.keystr == strbuf) 633 explicit_bzero(cfg.keystr, SIZE); 634 else 635 explicit_bzero(cfg.keystr, 636 strlen(cfg.keystr)); 637 } 638 if (cfg.hiv != NULL && !set_hex(cfg.hiv, iv, sizeof iv)) { 639 BIO_printf(bio_err, "invalid hex iv value\n"); 640 goto end; 641 } 642 if (cfg.hiv == NULL && cfg.keystr == NULL && 643 EVP_CIPHER_iv_length(cfg.cipher) != 0) { 644 /* 645 * No IV was explicitly set and no IV was generated 646 * during EVP_BytesToKey. Hence the IV is undefined, 647 * making correct decryption impossible. 648 */ 649 BIO_printf(bio_err, "iv undefined\n"); 650 goto end; 651 } 652 if (cfg.hkey != NULL && !set_hex(cfg.hkey, key, sizeof key)) { 653 BIO_printf(bio_err, "invalid hex key value\n"); 654 goto end; 655 } 656 if ((benc = BIO_new(BIO_f_cipher())) == NULL) 657 goto end; 658 659 /* 660 * Since we may be changing parameters work on the encryption 661 * context rather than calling BIO_set_cipher(). 662 */ 663 664 BIO_get_cipher_ctx(benc, &ctx); 665 666 if (!EVP_CipherInit_ex(ctx, cfg.cipher, NULL, NULL, 667 NULL, cfg.enc)) { 668 BIO_printf(bio_err, "Error setting cipher %s\n", 669 EVP_CIPHER_name(cfg.cipher)); 670 ERR_print_errors(bio_err); 671 goto end; 672 } 673 if (cfg.nopad) 674 EVP_CIPHER_CTX_set_padding(ctx, 0); 675 676 if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, cfg.enc)) { 677 BIO_printf(bio_err, "Error setting cipher %s\n", 678 EVP_CIPHER_name(cfg.cipher)); 679 ERR_print_errors(bio_err); 680 goto end; 681 } 682 if (cfg.debug) { 683 BIO_set_callback(benc, BIO_debug_callback); 684 BIO_set_callback_arg(benc, (char *) bio_err); 685 } 686 if (cfg.printkey) { 687 int key_len, iv_len; 688 689 if (!cfg.nosalt) { 690 printf("salt="); 691 for (i = 0; i < (int) sizeof(salt); i++) 692 printf("%02X", salt[i]); 693 printf("\n"); 694 } 695 key_len = EVP_CIPHER_key_length(cfg.cipher); 696 if (key_len > 0) { 697 printf("key="); 698 for (i = 0; i < key_len; i++) 699 printf("%02X", key[i]); 700 printf("\n"); 701 } 702 iv_len = EVP_CIPHER_iv_length(cfg.cipher); 703 if (iv_len > 0) { 704 printf("iv ="); 705 for (i = 0; i < iv_len; i++) 706 printf("%02X", iv[i]); 707 printf("\n"); 708 } 709 if (cfg.printkey == 2) { 710 ret = 0; 711 goto end; 712 } 713 } 714 } 715 /* Only encrypt/decrypt as we write the file */ 716 if (benc != NULL) 717 wbio = BIO_push(benc, wbio); 718 719 for (;;) { 720 inl = BIO_read(rbio, (char *) buff, bsize); 721 if (inl <= 0) 722 break; 723 if (BIO_write(wbio, (char *) buff, inl) != inl) { 724 BIO_printf(bio_err, "error writing output file\n"); 725 goto end; 726 } 727 } 728 if (!BIO_flush(wbio)) { 729 BIO_printf(bio_err, "bad decrypt\n"); 730 goto end; 731 } 732 ret = 0; 733 if (cfg.verbose) { 734 BIO_printf(bio_err, "bytes read :%8ld\n", BIO_number_read(in)); 735 BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out)); 736 } 737 end: 738 ERR_print_errors(bio_err); 739 free(strbuf); 740 free(buff); 741 BIO_free(in); 742 BIO_free_all(out); 743 BIO_free(benc); 744 BIO_free(b64); 745 free(pass); 746 747 return (ret); 748 } 749 750 int 751 set_hex(char *in, unsigned char *out, int size) 752 { 753 int i, n; 754 unsigned char j; 755 756 n = strlen(in); 757 if (n > (size * 2)) { 758 BIO_printf(bio_err, "hex string is too long\n"); 759 return (0); 760 } 761 memset(out, 0, size); 762 for (i = 0; i < n; i++) { 763 j = (unsigned char) *in; 764 *(in++) = '\0'; 765 if (j == 0) 766 break; 767 if (j >= '0' && j <= '9') 768 j -= '0'; 769 else if (j >= 'A' && j <= 'F') 770 j = j - 'A' + 10; 771 else if (j >= 'a' && j <= 'f') 772 j = j - 'a' + 10; 773 else { 774 BIO_printf(bio_err, "non-hex digit\n"); 775 return (0); 776 } 777 if (i & 1) 778 out[i / 2] |= j; 779 else 780 out[i / 2] = (j << 4); 781 } 782 return (1); 783 } 784