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