Annotation of src/usr.bin/openssl/enc.c, Revision 1.5
1.5 ! jsing 1: /* $OpenBSD: enc.c,v 1.4 2015/01/01 13:55: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
332: enc_main(int argc, char **argv)
333: {
334: static const char magic[] = "Salted__";
335: char mbuf[sizeof magic - 1];
1.4 jsing 336: char *strbuf = NULL, *pass = NULL;
337: unsigned char *buff = NULL;
338: int bsize = BSIZE;
1.1 jsing 339: int ret = 1, inl;
340: unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
341: unsigned char salt[PKCS5_SALT_LEN];
342: #ifdef ZLIB
343: BIO *bzl = NULL;
344: #endif
345: EVP_CIPHER_CTX *ctx = NULL;
1.4 jsing 346: const EVP_MD *dgst = NULL;
347: BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL;
348: BIO *rbio = NULL, *wbio = NULL;
1.1 jsing 349: #define PROG_NAME_SIZE 39
350: char pname[PROG_NAME_SIZE + 1];
1.4 jsing 351: int i;
352:
353: memset(&enc_config, 0, sizeof(enc_config));
354: enc_config.enc = 1;
1.1 jsing 355:
356: /* first check the program name */
1.4 jsing 357: program_name(argv[0], pname, sizeof(pname));
358:
1.1 jsing 359: if (strcmp(pname, "base64") == 0)
1.4 jsing 360: enc_config.base64 = 1;
361:
1.1 jsing 362: #ifdef ZLIB
363: if (strcmp(pname, "zlib") == 0)
1.4 jsing 364: enc_config.do_zlib = 1;
1.1 jsing 365: #endif
366:
1.4 jsing 367: enc_config.cipher = EVP_get_cipherbyname(pname);
368:
1.1 jsing 369: #ifdef ZLIB
1.4 jsing 370: if (!enc_config.do_zlib && !enc_config.base64 &&
371: enc_config.cipher == NULL && strcmp(pname, "enc") != 0)
1.1 jsing 372: #else
1.4 jsing 373: if (!enc_config.base64 && enc_config.cipher == NULL &&
374: strcmp(pname, "enc") != 0)
1.1 jsing 375: #endif
376: {
377: BIO_printf(bio_err, "%s is an unknown cipher\n", pname);
1.4 jsing 378: goto end;
379: }
380:
381: if (options_parse(argc, argv, enc_options, NULL, NULL) != 0) {
382: enc_usage();
383: goto end;
1.1 jsing 384: }
1.4 jsing 385:
386: if (enc_config.keyfile != NULL) {
387: static char buf[128];
388: FILE *infile;
389:
390: infile = fopen(enc_config.keyfile, "r");
391: if (infile == NULL) {
392: BIO_printf(bio_err, "unable to read key from '%s'\n",
393: enc_config.keyfile);
394: goto end;
1.1 jsing 395: }
1.4 jsing 396: buf[0] = '\0';
397: if (!fgets(buf, sizeof buf, infile)) {
398: BIO_printf(bio_err, "unable to read key from '%s'\n",
399: enc_config.keyfile);
400: fclose(infile);
401: goto end;
1.1 jsing 402: }
1.4 jsing 403: fclose(infile);
404: i = strlen(buf);
405: if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r')))
406: buf[--i] = '\0';
407: if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r')))
408: buf[--i] = '\0';
409: if (i < 1) {
410: BIO_printf(bio_err, "zero length password\n");
1.1 jsing 411: goto end;
412: }
1.4 jsing 413: enc_config.keystr = buf;
1.1 jsing 414: }
415:
416: #ifndef OPENSSL_NO_ENGINE
1.4 jsing 417: setup_engine(bio_err, enc_config.engine, 0);
1.1 jsing 418: #endif
419:
1.4 jsing 420: if (enc_config.md != NULL &&
421: (dgst = EVP_get_digestbyname(enc_config.md)) == NULL) {
422: BIO_printf(bio_err,
423: "%s is an unsupported message digest type\n",
424: enc_config.md);
1.1 jsing 425: goto end;
426: }
427: if (dgst == NULL) {
1.4 jsing 428: dgst = EVP_md5(); /* XXX */
1.1 jsing 429: }
1.4 jsing 430:
431: if (enc_config.bufsize != NULL) {
432: char *p = enc_config.bufsize;
1.1 jsing 433: unsigned long n;
434:
1.4 jsing 435: /* XXX - provide an OPTION_ARG_DISKUNIT. */
436: for (n = 0; *p != '\0'; p++) {
437: i = *p;
1.1 jsing 438: if ((i <= '9') && (i >= '0'))
439: n = n * 10 + i - '0';
440: else if (i == 'k') {
441: n *= 1024;
1.4 jsing 442: p++;
1.1 jsing 443: break;
444: }
445: }
1.4 jsing 446: if (*p != '\0') {
1.1 jsing 447: BIO_printf(bio_err, "invalid 'bufsize' specified.\n");
448: goto end;
449: }
1.4 jsing 450: /* It must be large enough for a base64 encoded line. */
451: if (enc_config.base64 && n < 80)
1.1 jsing 452: n = 80;
453:
1.4 jsing 454: bsize = (int)n;
455: if (enc_config.verbose)
1.1 jsing 456: BIO_printf(bio_err, "bufsize=%d\n", bsize);
457: }
458: strbuf = malloc(SIZE);
459: buff = malloc(EVP_ENCODE_LENGTH(bsize));
460: if ((buff == NULL) || (strbuf == NULL)) {
461: BIO_printf(bio_err, "malloc failure %ld\n", (long) EVP_ENCODE_LENGTH(bsize));
462: goto end;
463: }
464: in = BIO_new(BIO_s_file());
465: out = BIO_new(BIO_s_file());
466: if ((in == NULL) || (out == NULL)) {
467: ERR_print_errors(bio_err);
468: goto end;
469: }
1.4 jsing 470: if (enc_config.debug) {
1.1 jsing 471: BIO_set_callback(in, BIO_debug_callback);
472: BIO_set_callback(out, BIO_debug_callback);
473: BIO_set_callback_arg(in, (char *) bio_err);
474: BIO_set_callback_arg(out, (char *) bio_err);
475: }
1.4 jsing 476: if (enc_config.inf == NULL) {
477: if (enc_config.bufsize != NULL)
1.1 jsing 478: setvbuf(stdin, (char *) NULL, _IONBF, 0);
479: BIO_set_fp(in, stdin, BIO_NOCLOSE);
480: } else {
1.4 jsing 481: if (BIO_read_filename(in, enc_config.inf) <= 0) {
482: perror(enc_config.inf);
1.1 jsing 483: goto end;
484: }
485: }
486:
1.4 jsing 487: if (!enc_config.keystr && enc_config.passarg) {
488: if (!app_passwd(bio_err, enc_config.passarg, NULL,
489: &pass, NULL)) {
1.1 jsing 490: BIO_printf(bio_err, "Error getting password\n");
491: goto end;
492: }
1.4 jsing 493: enc_config.keystr = pass;
1.1 jsing 494: }
1.4 jsing 495: if (enc_config.keystr == NULL && enc_config.cipher != NULL &&
496: enc_config.hkey == NULL) {
1.1 jsing 497: for (;;) {
498: char buf[200];
1.2 doug 499: int retval;
1.1 jsing 500:
1.4 jsing 501: retval = snprintf(buf, sizeof buf,
502: "enter %s %s password:",
503: OBJ_nid2ln(EVP_CIPHER_nid(enc_config.cipher)),
504: enc_config.enc ? "encryption" : "decryption");
1.2 doug 505: if ((size_t)retval >= sizeof buf) {
1.4 jsing 506: BIO_printf(bio_err,
507: "Password prompt too long\n");
1.1 jsing 508: goto end;
509: }
510: strbuf[0] = '\0';
1.4 jsing 511: i = EVP_read_pw_string((char *)strbuf, SIZE, buf,
512: enc_config.enc);
1.1 jsing 513: if (i == 0) {
514: if (strbuf[0] == '\0') {
515: ret = 1;
516: goto end;
517: }
1.4 jsing 518: enc_config.keystr = strbuf;
1.1 jsing 519: break;
520: }
521: if (i < 0) {
522: BIO_printf(bio_err, "bad password read\n");
523: goto end;
524: }
525: }
526: }
1.4 jsing 527: if (enc_config.outf == NULL) {
1.1 jsing 528: BIO_set_fp(out, stdout, BIO_NOCLOSE);
1.4 jsing 529: if (enc_config.bufsize != NULL)
530: setvbuf(stdout, (char *)NULL, _IONBF, 0);
1.1 jsing 531: } else {
1.4 jsing 532: if (BIO_write_filename(out, enc_config.outf) <= 0) {
533: perror(enc_config.outf);
1.1 jsing 534: goto end;
535: }
536: }
537:
538: rbio = in;
539: wbio = out;
540:
541: #ifdef ZLIB
542: if (do_zlib) {
543: if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
544: goto end;
545: if (enc)
546: wbio = BIO_push(bzl, wbio);
547: else
548: rbio = BIO_push(bzl, rbio);
549: }
550: #endif
551:
1.4 jsing 552: if (enc_config.base64) {
1.1 jsing 553: if ((b64 = BIO_new(BIO_f_base64())) == NULL)
554: goto end;
1.4 jsing 555: if (enc_config.debug) {
1.1 jsing 556: BIO_set_callback(b64, BIO_debug_callback);
557: BIO_set_callback_arg(b64, (char *) bio_err);
558: }
1.4 jsing 559: if (enc_config.olb64)
1.1 jsing 560: BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1.4 jsing 561: if (enc_config.enc)
1.1 jsing 562: wbio = BIO_push(b64, wbio);
563: else
564: rbio = BIO_push(b64, rbio);
565: }
1.4 jsing 566: if (enc_config.cipher != NULL) {
1.1 jsing 567: /*
1.4 jsing 568: * Note that keystr is NULL if a key was passed on the command
1.1 jsing 569: * line, so we get no salt in that case. Is this a bug?
570: */
1.4 jsing 571: if (enc_config.keystr != NULL) {
1.1 jsing 572: /*
573: * Salt handling: if encrypting generate a salt and
574: * write to output BIO. If decrypting read salt from
575: * input BIO.
576: */
577: unsigned char *sptr;
1.4 jsing 578: if (enc_config.nosalt)
1.1 jsing 579: sptr = NULL;
580: else {
1.4 jsing 581: if (enc_config.enc) {
582: if (enc_config.hsalt) {
583: if (!set_hex(enc_config.hsalt, salt, sizeof salt)) {
1.1 jsing 584: BIO_printf(bio_err,
585: "invalid hex salt value\n");
586: goto end;
587: }
1.3 jsing 588: } else
589: arc4random_buf(salt,
590: sizeof(salt));
1.1 jsing 591: /*
592: * If -P option then don't bother
593: * writing
594: */
1.4 jsing 595: if ((enc_config.printkey != 2)
1.1 jsing 596: && (BIO_write(wbio, magic,
597: sizeof magic - 1) != sizeof magic - 1
598: || BIO_write(wbio,
599: (char *) salt,
600: sizeof salt) != sizeof salt)) {
601: BIO_printf(bio_err, "error writing output file\n");
602: goto end;
603: }
604: } else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf
605: || BIO_read(rbio,
606: (unsigned char *) salt,
607: sizeof salt) != sizeof salt) {
608: BIO_printf(bio_err, "error reading input file\n");
609: goto end;
610: } else if (memcmp(mbuf, magic, sizeof magic - 1)) {
611: BIO_printf(bio_err, "bad magic number\n");
612: goto end;
613: }
614: sptr = salt;
615: }
616:
1.4 jsing 617: EVP_BytesToKey(enc_config.cipher, dgst, sptr,
618: (unsigned char *)enc_config.keystr,
619: strlen(enc_config.keystr), 1, key, iv);
1.1 jsing 620: /*
621: * zero the complete buffer or the string passed from
622: * the command line bug picked up by Larry J. Hughes
623: * Jr. <hughes@indiana.edu>
624: */
1.4 jsing 625: if (enc_config.keystr == strbuf)
626: OPENSSL_cleanse(enc_config.keystr, SIZE);
1.1 jsing 627: else
1.4 jsing 628: OPENSSL_cleanse(enc_config.keystr,
629: strlen(enc_config.keystr));
1.1 jsing 630: }
1.4 jsing 631: if (enc_config.hiv != NULL &&
632: !set_hex(enc_config.hiv, iv, sizeof iv)) {
1.1 jsing 633: BIO_printf(bio_err, "invalid hex iv value\n");
634: goto end;
635: }
1.4 jsing 636: if (enc_config.hiv == NULL && enc_config.keystr == NULL &&
637: EVP_CIPHER_iv_length(enc_config.cipher) != 0) {
1.1 jsing 638: /*
639: * No IV was explicitly set and no IV was generated
640: * during EVP_BytesToKey. Hence the IV is undefined,
641: * making correct decryption impossible.
642: */
643: BIO_printf(bio_err, "iv undefined\n");
644: goto end;
645: }
1.4 jsing 646: if (enc_config.hkey != NULL &&
647: !set_hex(enc_config.hkey, key, sizeof key)) {
1.1 jsing 648: BIO_printf(bio_err, "invalid hex key value\n");
649: goto end;
650: }
651: if ((benc = BIO_new(BIO_f_cipher())) == NULL)
652: goto end;
653:
654: /*
655: * Since we may be changing parameters work on the encryption
656: * context rather than calling BIO_set_cipher().
657: */
658:
659: BIO_get_cipher_ctx(benc, &ctx);
660:
1.4 jsing 661: if (!EVP_CipherInit_ex(ctx, enc_config.cipher, NULL, NULL,
662: NULL, enc_config.enc)) {
1.1 jsing 663: BIO_printf(bio_err, "Error setting cipher %s\n",
1.4 jsing 664: EVP_CIPHER_name(enc_config.cipher));
1.1 jsing 665: ERR_print_errors(bio_err);
666: goto end;
667: }
1.4 jsing 668: if (enc_config.nopad)
1.1 jsing 669: EVP_CIPHER_CTX_set_padding(ctx, 0);
670:
1.4 jsing 671: if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv,
672: enc_config.enc)) {
1.1 jsing 673: BIO_printf(bio_err, "Error setting cipher %s\n",
1.4 jsing 674: EVP_CIPHER_name(enc_config.cipher));
1.1 jsing 675: ERR_print_errors(bio_err);
676: goto end;
677: }
1.4 jsing 678: if (enc_config.debug) {
1.1 jsing 679: BIO_set_callback(benc, BIO_debug_callback);
680: BIO_set_callback_arg(benc, (char *) bio_err);
681: }
1.4 jsing 682: if (enc_config.printkey) {
683: if (!enc_config.nosalt) {
1.1 jsing 684: printf("salt=");
685: for (i = 0; i < (int) sizeof(salt); i++)
686: printf("%02X", salt[i]);
687: printf("\n");
688: }
1.4 jsing 689: if (enc_config.cipher->key_len > 0) {
1.1 jsing 690: printf("key=");
1.4 jsing 691: for (i = 0; i < enc_config.cipher->key_len; i++)
1.1 jsing 692: printf("%02X", key[i]);
693: printf("\n");
694: }
1.4 jsing 695: if (enc_config.cipher->iv_len > 0) {
1.1 jsing 696: printf("iv =");
1.4 jsing 697: for (i = 0; i < enc_config.cipher->iv_len; i++)
1.1 jsing 698: printf("%02X", iv[i]);
699: printf("\n");
700: }
1.4 jsing 701: if (enc_config.printkey == 2) {
1.1 jsing 702: ret = 0;
703: goto end;
704: }
705: }
706: }
707: /* Only encrypt/decrypt as we write the file */
708: if (benc != NULL)
709: wbio = BIO_push(benc, wbio);
710:
711: for (;;) {
712: inl = BIO_read(rbio, (char *) buff, bsize);
713: if (inl <= 0)
714: break;
715: if (BIO_write(wbio, (char *) buff, inl) != inl) {
716: BIO_printf(bio_err, "error writing output file\n");
717: goto end;
718: }
719: }
720: if (!BIO_flush(wbio)) {
721: BIO_printf(bio_err, "bad decrypt\n");
722: goto end;
723: }
724: ret = 0;
1.4 jsing 725: if (enc_config.verbose) {
1.1 jsing 726: BIO_printf(bio_err, "bytes read :%8ld\n", BIO_number_read(in));
727: BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out));
728: }
729: end:
730: ERR_print_errors(bio_err);
731: free(strbuf);
732: free(buff);
733: BIO_free(in);
734: if (out != NULL)
735: BIO_free_all(out);
736: BIO_free(benc);
737: BIO_free(b64);
738: #ifdef ZLIB
739: BIO_free(bzl);
740: #endif
741: free(pass);
742:
743: return (ret);
744: }
745:
746: int
747: set_hex(char *in, unsigned char *out, int size)
748: {
749: int i, n;
750: unsigned char j;
751:
752: n = strlen(in);
753: if (n > (size * 2)) {
754: BIO_printf(bio_err, "hex string is too long\n");
755: return (0);
756: }
757: memset(out, 0, size);
758: for (i = 0; i < n; i++) {
759: j = (unsigned char) *in;
760: *(in++) = '\0';
761: if (j == 0)
762: break;
763: if ((j >= '0') && (j <= '9'))
764: j -= '0';
765: else if ((j >= 'A') && (j <= 'F'))
766: j = j - 'A' + 10;
767: else if ((j >= 'a') && (j <= 'f'))
768: j = j - 'a' + 10;
769: else {
770: BIO_printf(bio_err, "non-hex digit\n");
771: return (0);
772: }
773: if (i & 1)
774: out[i / 2] |= j;
775: else
776: out[i / 2] = (j << 4);
777: }
778: return (1);
779: }