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