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