1 /* $OpenBSD: enc.c,v 1.14 2018/02/07 05:47:55 jsing Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
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.
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).
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.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
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)"
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
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.]
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>
74 int set_hex(char *in
, unsigned char *out
, int size
);
77 #define BSIZE (8*1024)
82 const EVP_CIPHER
*cipher
;
105 enc_opt_cipher(int argc
, char **argv
, int *argsused
)
107 char *name
= argv
[0];
112 if (strcmp(name
, "none") == 0) {
113 enc_config
.cipher
= NULL
;
118 if ((enc_config
.cipher
= EVP_get_cipherbyname(name
)) != NULL
) {
126 static struct option enc_options
[] = {
129 .desc
= "Process base64 data on one line (requires -a)",
131 .opt
.flag
= &enc_config
.olb64
,
135 .desc
= "Perform base64 encoding/decoding (alias -base64)",
137 .opt
.flag
= &enc_config
.base64
,
142 .opt
.flag
= &enc_config
.base64
,
147 .desc
= "Specify the buffer size to use for I/O",
149 .opt
.arg
= &enc_config
.bufsize
,
153 .desc
= "Decrypt the input data",
154 .type
= OPTION_VALUE
,
155 .opt
.value
= &enc_config
.enc
,
160 .desc
= "Print debugging information",
162 .opt
.flag
= &enc_config
.debug
,
166 .desc
= "Encrypt the input data (default)",
167 .type
= OPTION_VALUE
,
168 .opt
.value
= &enc_config
.enc
,
174 .desc
= "Input file to read from (default stdin)",
176 .opt
.arg
= &enc_config
.inf
,
181 .desc
= "IV to use, specified as a hexadecimal string",
183 .opt
.arg
= &enc_config
.hiv
,
188 .desc
= "Key to use, specified as a hexadecimal string",
190 .opt
.arg
= &enc_config
.hkey
,
193 .name
= "k", /* Superseded by -pass. */
195 .opt
.arg
= &enc_config
.keystr
,
198 .name
= "kfile", /* Superseded by -pass. */
200 .opt
.arg
= &enc_config
.keyfile
,
205 .desc
= "Digest to use to create a key from the passphrase",
207 .opt
.arg
= &enc_config
.md
,
211 .desc
= "Use NULL cipher (no encryption or decryption)",
212 .type
= OPTION_ARGV_FUNC
,
213 .opt
.argvfunc
= enc_opt_cipher
,
217 .desc
= "Disable standard block padding",
219 .opt
.flag
= &enc_config
.nopad
,
223 .type
= OPTION_VALUE
,
224 .opt
.value
= &enc_config
.nosalt
,
230 .desc
= "Output file to write to (default stdout)",
232 .opt
.arg
= &enc_config
.outf
,
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
,
244 .desc
= "Print out the salt, key and IV used",
245 .type
= OPTION_VALUE
,
246 .opt
.value
= &enc_config
.printkey
,
252 .desc
= "Password source",
254 .opt
.arg
= &enc_config
.passarg
,
259 .desc
= "Salt to use, specified as a hexadecimal string",
261 .opt
.arg
= &enc_config
.hsalt
,
265 .desc
= "Use a salt in the key derivation routines (default)",
266 .type
= OPTION_VALUE
,
267 .opt
.value
= &enc_config
.nosalt
,
274 .opt
.flag
= &enc_config
.verbose
,
279 .desc
= "Perform zlib compression/decompression",
281 .opt
.flag
= &enc_config
.do_zlib
,
286 .type
= OPTION_ARGV_FUNC
,
287 .opt
.argvfunc
= enc_opt_cipher
,
293 show_ciphers(const OBJ_NAME
*name
, void *arg
)
297 if (!islower((unsigned char)*name
->name
))
300 fprintf(stderr
, " -%-24s%s", name
->name
, (++n
% 3 ? "" : "\n"));
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");
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");
320 enc_main(int argc
, char **argv
)
322 static const char magic
[] = "Salted__";
323 char mbuf
[sizeof magic
- 1];
324 char *strbuf
= NULL
, *pass
= NULL
;
325 unsigned char *buff
= NULL
;
328 unsigned char key
[EVP_MAX_KEY_LENGTH
], iv
[EVP_MAX_IV_LENGTH
];
329 unsigned char salt
[PKCS5_SALT_LEN
];
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];
341 if (single_execution
) {
342 if (pledge("stdio cpath wpath rpath tty", NULL
) == -1) {
348 memset(&enc_config
, 0, sizeof(enc_config
));
351 /* first check the program name */
352 program_name(argv
[0], pname
, sizeof(pname
));
354 if (strcmp(pname
, "base64") == 0)
355 enc_config
.base64
= 1;
358 if (strcmp(pname
, "zlib") == 0)
359 enc_config
.do_zlib
= 1;
362 enc_config
.cipher
= EVP_get_cipherbyname(pname
);
365 if (!enc_config
.do_zlib
&& !enc_config
.base64
&&
366 enc_config
.cipher
== NULL
&& strcmp(pname
, "enc") != 0)
368 if (!enc_config
.base64
&& enc_config
.cipher
== NULL
&&
369 strcmp(pname
, "enc") != 0)
372 BIO_printf(bio_err
, "%s is an unknown cipher\n", pname
);
376 if (options_parse(argc
, argv
, enc_options
, NULL
, NULL
) != 0) {
381 if (enc_config
.keyfile
!= NULL
) {
382 static char buf
[128];
385 infile
= fopen(enc_config
.keyfile
, "r");
386 if (infile
== NULL
) {
387 BIO_printf(bio_err
, "unable to read key from '%s'\n",
392 if (!fgets(buf
, sizeof buf
, infile
)) {
393 BIO_printf(bio_err
, "unable to read key from '%s'\n",
400 if ((i
> 0) && ((buf
[i
- 1] == '\n') || (buf
[i
- 1] == '\r')))
402 if ((i
> 0) && ((buf
[i
- 1] == '\n') || (buf
[i
- 1] == '\r')))
405 BIO_printf(bio_err
, "zero length password\n");
408 enc_config
.keystr
= buf
;
411 if (enc_config
.md
!= NULL
&&
412 (dgst
= EVP_get_digestbyname(enc_config
.md
)) == NULL
) {
414 "%s is an unsupported message digest type\n",
419 dgst
= EVP_md5(); /* XXX */
422 if (enc_config
.bufsize
!= NULL
) {
423 char *p
= enc_config
.bufsize
;
426 /* XXX - provide an OPTION_ARG_DISKUNIT. */
427 for (n
= 0; *p
!= '\0'; p
++) {
429 if ((i
<= '9') && (i
>= '0'))
430 n
= n
* 10 + i
- '0';
438 BIO_printf(bio_err
, "invalid 'bufsize' specified.\n");
441 /* It must be large enough for a base64 encoded line. */
442 if (enc_config
.base64
&& n
< 80)
446 if (enc_config
.verbose
)
447 BIO_printf(bio_err
, "bufsize=%d\n", bsize
);
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
));
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
);
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
);
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
);
472 if (BIO_read_filename(in
, enc_config
.inf
) <= 0) {
473 perror(enc_config
.inf
);
478 if (!enc_config
.keystr
&& enc_config
.passarg
) {
479 if (!app_passwd(bio_err
, enc_config
.passarg
, NULL
,
481 BIO_printf(bio_err
, "Error getting password\n");
484 enc_config
.keystr
= pass
;
486 if (enc_config
.keystr
== NULL
&& enc_config
.cipher
!= NULL
&&
487 enc_config
.hkey
== NULL
) {
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
) {
498 "Password prompt too long\n");
502 i
= EVP_read_pw_string((char *)strbuf
, SIZE
, buf
,
505 if (strbuf
[0] == '\0') {
509 enc_config
.keystr
= strbuf
;
513 BIO_printf(bio_err
, "bad password read\n");
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);
523 if (BIO_write_filename(out
, enc_config
.outf
) <= 0) {
524 perror(enc_config
.outf
);
534 if ((bzl
= BIO_new(BIO_f_zlib())) == NULL
)
537 wbio
= BIO_push(bzl
, wbio
);
539 rbio
= BIO_push(bzl
, rbio
);
543 if (enc_config
.base64
) {
544 if ((b64
= BIO_new(BIO_f_base64())) == NULL
)
546 if (enc_config
.debug
) {
547 BIO_set_callback(b64
, BIO_debug_callback
);
548 BIO_set_callback_arg(b64
, (char *) bio_err
);
550 if (enc_config
.olb64
)
551 BIO_set_flags(b64
, BIO_FLAGS_BASE64_NO_NL
);
553 wbio
= BIO_push(b64
, wbio
);
555 rbio
= BIO_push(b64
, rbio
);
557 if (enc_config
.cipher
!= NULL
) {
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?
562 if (enc_config
.keystr
!= NULL
) {
564 * Salt handling: if encrypting generate a salt and
565 * write to output BIO. If decrypting read salt from
569 if (enc_config
.nosalt
)
572 if (enc_config
.enc
) {
573 if (enc_config
.hsalt
) {
574 if (!set_hex(enc_config
.hsalt
, salt
, sizeof salt
)) {
576 "invalid hex salt value\n");
583 * If -P option then don't bother
586 if ((enc_config
.printkey
!= 2)
587 && (BIO_write(wbio
, magic
,
588 sizeof magic
- 1) != sizeof magic
- 1
591 sizeof salt
) != sizeof salt
)) {
592 BIO_printf(bio_err
, "error writing output file\n");
595 } else if (BIO_read(rbio
, mbuf
, sizeof mbuf
) != sizeof mbuf
597 (unsigned char *) salt
,
598 sizeof salt
) != sizeof salt
) {
599 BIO_printf(bio_err
, "error reading input file\n");
601 } else if (memcmp(mbuf
, magic
, sizeof magic
- 1)) {
602 BIO_printf(bio_err
, "bad magic number\n");
608 EVP_BytesToKey(enc_config
.cipher
, dgst
, sptr
,
609 (unsigned char *)enc_config
.keystr
,
610 strlen(enc_config
.keystr
), 1, key
, iv
);
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>
616 if (enc_config
.keystr
== strbuf
)
617 explicit_bzero(enc_config
.keystr
, SIZE
);
619 explicit_bzero(enc_config
.keystr
,
620 strlen(enc_config
.keystr
));
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");
627 if (enc_config
.hiv
== NULL
&& enc_config
.keystr
== NULL
&&
628 EVP_CIPHER_iv_length(enc_config
.cipher
) != 0) {
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.
634 BIO_printf(bio_err
, "iv undefined\n");
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");
642 if ((benc
= BIO_new(BIO_f_cipher())) == NULL
)
646 * Since we may be changing parameters work on the encryption
647 * context rather than calling BIO_set_cipher().
650 BIO_get_cipher_ctx(benc
, &ctx
);
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
);
659 if (enc_config
.nopad
)
660 EVP_CIPHER_CTX_set_padding(ctx
, 0);
662 if (!EVP_CipherInit_ex(ctx
, NULL
, NULL
, key
, iv
,
664 BIO_printf(bio_err
, "Error setting cipher %s\n",
665 EVP_CIPHER_name(enc_config
.cipher
));
666 ERR_print_errors(bio_err
);
669 if (enc_config
.debug
) {
670 BIO_set_callback(benc
, BIO_debug_callback
);
671 BIO_set_callback_arg(benc
, (char *) bio_err
);
673 if (enc_config
.printkey
) {
674 if (!enc_config
.nosalt
) {
676 for (i
= 0; i
< (int) sizeof(salt
); i
++)
677 printf("%02X", salt
[i
]);
680 if (enc_config
.cipher
->key_len
> 0) {
682 for (i
= 0; i
< enc_config
.cipher
->key_len
; i
++)
683 printf("%02X", key
[i
]);
686 if (enc_config
.cipher
->iv_len
> 0) {
688 for (i
= 0; i
< enc_config
.cipher
->iv_len
; i
++)
689 printf("%02X", iv
[i
]);
692 if (enc_config
.printkey
== 2) {
698 /* Only encrypt/decrypt as we write the file */
700 wbio
= BIO_push(benc
, wbio
);
703 inl
= BIO_read(rbio
, (char *) buff
, bsize
);
706 if (BIO_write(wbio
, (char *) buff
, inl
) != inl
) {
707 BIO_printf(bio_err
, "error writing output file\n");
711 if (!BIO_flush(wbio
)) {
712 BIO_printf(bio_err
, "bad decrypt\n");
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
));
721 ERR_print_errors(bio_err
);
737 set_hex(char *in
, unsigned char *out
, int size
)
743 if (n
> (size
* 2)) {
744 BIO_printf(bio_err
, "hex string is too long\n");
747 memset(out
, 0, size
);
748 for (i
= 0; i
< n
; i
++) {
749 j
= (unsigned char) *in
;
753 if ((j
>= '0') && (j
<= '9'))
755 else if ((j
>= 'A') && (j
<= 'F'))
757 else if ((j
>= 'a') && (j
<= 'f'))
760 BIO_printf(bio_err
, "non-hex digit\n");
766 out
[i
/ 2] = (j
<< 4);