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