1 |
|
|
/* $OpenBSD: enc.c,v 1.11 2016/04/07 20:02:19 jmc 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 hexadecimal 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 hexadecimal 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 hexadecimal 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 |
|
|
if (single_execution) { |
342 |
|
|
if (pledge("stdio rpath wpath cpath tty", NULL) == -1) { |
343 |
|
|
perror("pledge"); |
344 |
|
|
exit(1); |
345 |
|
|
} |
346 |
|
|
} |
347 |
|
|
|
348 |
|
|
memset(&enc_config, 0, sizeof(enc_config)); |
349 |
|
|
enc_config.enc = 1; |
350 |
|
|
|
351 |
|
|
/* first check the program name */ |
352 |
|
|
program_name(argv[0], pname, sizeof(pname)); |
353 |
|
|
|
354 |
|
|
if (strcmp(pname, "base64") == 0) |
355 |
|
|
enc_config.base64 = 1; |
356 |
|
|
|
357 |
|
|
#ifdef ZLIB |
358 |
|
|
if (strcmp(pname, "zlib") == 0) |
359 |
|
|
enc_config.do_zlib = 1; |
360 |
|
|
#endif |
361 |
|
|
|
362 |
|
|
enc_config.cipher = EVP_get_cipherbyname(pname); |
363 |
|
|
|
364 |
|
|
#ifdef ZLIB |
365 |
|
|
if (!enc_config.do_zlib && !enc_config.base64 && |
366 |
|
|
enc_config.cipher == NULL && strcmp(pname, "enc") != 0) |
367 |
|
|
#else |
368 |
|
|
if (!enc_config.base64 && enc_config.cipher == NULL && |
369 |
|
|
strcmp(pname, "enc") != 0) |
370 |
|
|
#endif |
371 |
|
|
{ |
372 |
|
|
BIO_printf(bio_err, "%s is an unknown cipher\n", pname); |
373 |
|
|
goto end; |
374 |
|
|
} |
375 |
|
|
|
376 |
|
|
if (options_parse(argc, argv, enc_options, NULL, NULL) != 0) { |
377 |
|
|
enc_usage(); |
378 |
|
|
goto end; |
379 |
|
|
} |
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; |
390 |
|
|
} |
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; |
397 |
|
|
} |
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"); |
406 |
|
|
goto end; |
407 |
|
|
} |
408 |
|
|
enc_config.keystr = buf; |
409 |
|
|
} |
410 |
|
|
|
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); |
416 |
|
|
goto end; |
417 |
|
|
} |
418 |
|
|
if (dgst == NULL) { |
419 |
|
|
dgst = EVP_md5(); /* XXX */ |
420 |
|
|
} |
421 |
|
|
|
422 |
|
|
if (enc_config.bufsize != NULL) { |
423 |
|
|
char *p = enc_config.bufsize; |
424 |
|
|
unsigned long n; |
425 |
|
|
|
426 |
|
|
/* XXX - provide an OPTION_ARG_DISKUNIT. */ |
427 |
|
|
for (n = 0; *p != '\0'; p++) { |
428 |
|
|
i = *p; |
429 |
|
|
if ((i <= '9') && (i >= '0')) |
430 |
|
|
n = n * 10 + i - '0'; |
431 |
|
|
else if (i == 'k') { |
432 |
|
|
n *= 1024; |
433 |
|
|
p++; |
434 |
|
|
break; |
435 |
|
|
} |
436 |
|
|
} |
437 |
|
|
if (*p != '\0') { |
438 |
|
|
BIO_printf(bio_err, "invalid 'bufsize' specified.\n"); |
439 |
|
|
goto end; |
440 |
|
|
} |
441 |
|
|
/* It must be large enough for a base64 encoded line. */ |
442 |
|
|
if (enc_config.base64 && n < 80) |
443 |
|
|
n = 80; |
444 |
|
|
|
445 |
|
|
bsize = (int)n; |
446 |
|
|
if (enc_config.verbose) |
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 |
|
|
} |
461 |
|
|
if (enc_config.debug) { |
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 |
|
|
} |
467 |
|
|
if (enc_config.inf == NULL) { |
468 |
|
|
if (enc_config.bufsize != NULL) |
469 |
|
|
setvbuf(stdin, (char *) NULL, _IONBF, 0); |
470 |
|
|
BIO_set_fp(in, stdin, BIO_NOCLOSE); |
471 |
|
|
} else { |
472 |
|
|
if (BIO_read_filename(in, enc_config.inf) <= 0) { |
473 |
|
|
perror(enc_config.inf); |
474 |
|
|
goto end; |
475 |
|
|
} |
476 |
|
|
} |
477 |
|
|
|
478 |
|
|
if (!enc_config.keystr && enc_config.passarg) { |
479 |
|
|
if (!app_passwd(bio_err, enc_config.passarg, NULL, |
480 |
|
|
&pass, NULL)) { |
481 |
|
|
BIO_printf(bio_err, "Error getting password\n"); |
482 |
|
|
goto end; |
483 |
|
|
} |
484 |
|
|
enc_config.keystr = pass; |
485 |
|
|
} |
486 |
|
|
if (enc_config.keystr == NULL && enc_config.cipher != NULL && |
487 |
|
|
enc_config.hkey == NULL) { |
488 |
|
|
for (;;) { |
489 |
|
|
char buf[200]; |
490 |
|
|
int retval; |
491 |
|
|
|
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"); |
496 |
|
|
if ((size_t)retval >= sizeof buf) { |
497 |
|
|
BIO_printf(bio_err, |
498 |
|
|
"Password prompt too long\n"); |
499 |
|
|
goto end; |
500 |
|
|
} |
501 |
|
|
strbuf[0] = '\0'; |
502 |
|
|
i = EVP_read_pw_string((char *)strbuf, SIZE, buf, |
503 |
|
|
enc_config.enc); |
504 |
|
|
if (i == 0) { |
505 |
|
|
if (strbuf[0] == '\0') { |
506 |
|
|
ret = 1; |
507 |
|
|
goto end; |
508 |
|
|
} |
509 |
|
|
enc_config.keystr = strbuf; |
510 |
|
|
break; |
511 |
|
|
} |
512 |
|
|
if (i < 0) { |
513 |
|
|
BIO_printf(bio_err, "bad password read\n"); |
514 |
|
|
goto end; |
515 |
|
|
} |
516 |
|
|
} |
517 |
|
|
} |
518 |
|
|
if (enc_config.outf == NULL) { |
519 |
|
|
BIO_set_fp(out, stdout, BIO_NOCLOSE); |
520 |
|
|
if (enc_config.bufsize != NULL) |
521 |
|
|
setvbuf(stdout, (char *)NULL, _IONBF, 0); |
522 |
|
|
} else { |
523 |
|
|
if (BIO_write_filename(out, enc_config.outf) <= 0) { |
524 |
|
|
perror(enc_config.outf); |
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 |
|
|
|
543 |
|
|
if (enc_config.base64) { |
544 |
|
|
if ((b64 = BIO_new(BIO_f_base64())) == NULL) |
545 |
|
|
goto end; |
546 |
|
|
if (enc_config.debug) { |
547 |
|
|
BIO_set_callback(b64, BIO_debug_callback); |
548 |
|
|
BIO_set_callback_arg(b64, (char *) bio_err); |
549 |
|
|
} |
550 |
|
|
if (enc_config.olb64) |
551 |
|
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); |
552 |
|
|
if (enc_config.enc) |
553 |
|
|
wbio = BIO_push(b64, wbio); |
554 |
|
|
else |
555 |
|
|
rbio = BIO_push(b64, rbio); |
556 |
|
|
} |
557 |
|
|
if (enc_config.cipher != NULL) { |
558 |
|
|
/* |
559 |
|
|
* Note that keystr is NULL if a key was passed on the command |
560 |
|
|
* line, so we get no salt in that case. Is this a bug? |
561 |
|
|
*/ |
562 |
|
|
if (enc_config.keystr != NULL) { |
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; |
569 |
|
|
if (enc_config.nosalt) |
570 |
|
|
sptr = NULL; |
571 |
|
|
else { |
572 |
|
|
if (enc_config.enc) { |
573 |
|
|
if (enc_config.hsalt) { |
574 |
|
|
if (!set_hex(enc_config.hsalt, salt, sizeof salt)) { |
575 |
|
|
BIO_printf(bio_err, |
576 |
|
|
"invalid hex salt value\n"); |
577 |
|
|
goto end; |
578 |
|
|
} |
579 |
|
|
} else |
580 |
|
|
arc4random_buf(salt, |
581 |
|
|
sizeof(salt)); |
582 |
|
|
/* |
583 |
|
|
* If -P option then don't bother |
584 |
|
|
* writing |
585 |
|
|
*/ |
586 |
|
|
if ((enc_config.printkey != 2) |
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 |
|
|
|
608 |
|
|
EVP_BytesToKey(enc_config.cipher, dgst, sptr, |
609 |
|
|
(unsigned char *)enc_config.keystr, |
610 |
|
|
strlen(enc_config.keystr), 1, key, iv); |
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 |
|
|
*/ |
616 |
|
|
if (enc_config.keystr == strbuf) |
617 |
|
|
explicit_bzero(enc_config.keystr, SIZE); |
618 |
|
|
else |
619 |
|
|
explicit_bzero(enc_config.keystr, |
620 |
|
|
strlen(enc_config.keystr)); |
621 |
|
|
} |
622 |
|
|
if (enc_config.hiv != NULL && |
623 |
|
|
!set_hex(enc_config.hiv, iv, sizeof iv)) { |
624 |
|
|
BIO_printf(bio_err, "invalid hex iv value\n"); |
625 |
|
|
goto end; |
626 |
|
|
} |
627 |
|
|
if (enc_config.hiv == NULL && enc_config.keystr == NULL && |
628 |
|
|
EVP_CIPHER_iv_length(enc_config.cipher) != 0) { |
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 |
|
|
} |
637 |
|
|
if (enc_config.hkey != NULL && |
638 |
|
|
!set_hex(enc_config.hkey, key, sizeof key)) { |
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 |
|
|
|
652 |
|
|
if (!EVP_CipherInit_ex(ctx, enc_config.cipher, NULL, NULL, |
653 |
|
|
NULL, enc_config.enc)) { |
654 |
|
|
BIO_printf(bio_err, "Error setting cipher %s\n", |
655 |
|
|
EVP_CIPHER_name(enc_config.cipher)); |
656 |
|
|
ERR_print_errors(bio_err); |
657 |
|
|
goto end; |
658 |
|
|
} |
659 |
|
|
if (enc_config.nopad) |
660 |
|
|
EVP_CIPHER_CTX_set_padding(ctx, 0); |
661 |
|
|
|
662 |
|
|
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, |
663 |
|
|
enc_config.enc)) { |
664 |
|
|
BIO_printf(bio_err, "Error setting cipher %s\n", |
665 |
|
|
EVP_CIPHER_name(enc_config.cipher)); |
666 |
|
|
ERR_print_errors(bio_err); |
667 |
|
|
goto end; |
668 |
|
|
} |
669 |
|
|
if (enc_config.debug) { |
670 |
|
|
BIO_set_callback(benc, BIO_debug_callback); |
671 |
|
|
BIO_set_callback_arg(benc, (char *) bio_err); |
672 |
|
|
} |
673 |
|
|
if (enc_config.printkey) { |
674 |
|
|
if (!enc_config.nosalt) { |
675 |
|
|
printf("salt="); |
676 |
|
|
for (i = 0; i < (int) sizeof(salt); i++) |
677 |
|
|
printf("%02X", salt[i]); |
678 |
|
|
printf("\n"); |
679 |
|
|
} |
680 |
|
|
if (enc_config.cipher->key_len > 0) { |
681 |
|
|
printf("key="); |
682 |
|
|
for (i = 0; i < enc_config.cipher->key_len; i++) |
683 |
|
|
printf("%02X", key[i]); |
684 |
|
|
printf("\n"); |
685 |
|
|
} |
686 |
|
|
if (enc_config.cipher->iv_len > 0) { |
687 |
|
|
printf("iv ="); |
688 |
|
|
for (i = 0; i < enc_config.cipher->iv_len; i++) |
689 |
|
|
printf("%02X", iv[i]); |
690 |
|
|
printf("\n"); |
691 |
|
|
} |
692 |
|
|
if (enc_config.printkey == 2) { |
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; |
716 |
|
|
if (enc_config.verbose) { |
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 |
|
|
} |