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