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