source: trunk/third/openssl/apps/enc.c @ 19843

Revision 19843, 15.5 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19842, which included commits to RCS files with non-trunk default branches.
Line 
1/* apps/enc.c */
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 <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62#include "apps.h"
63#include <openssl/bio.h>
64#include <openssl/err.h>
65#include <openssl/evp.h>
66#include <openssl/objects.h>
67#include <openssl/x509.h>
68#include <openssl/rand.h>
69#include <openssl/pem.h>
70#include <ctype.h>
71
72int set_hex(char *in,unsigned char *out,int size);
73#undef SIZE
74#undef BSIZE
75#undef PROG
76
77#define SIZE    (512)
78#define BSIZE   (8*1024)
79#define PROG    enc_main
80
81static void show_ciphers(const OBJ_NAME *name,void *bio_)
82        {
83        BIO *bio=bio_;
84        static int n;
85
86        if(!islower((unsigned char)*name->name))
87                return;
88
89        BIO_printf(bio,"-%-25s",name->name);
90        if(++n == 3)
91                {
92                BIO_printf(bio,"\n");
93                n=0;
94                }
95        else
96                BIO_printf(bio," ");
97        }
98
99int MAIN(int, char **);
100
101int MAIN(int argc, char **argv)
102        {
103#ifndef OPENSSL_NO_ENGINE
104        ENGINE *e = NULL;
105#endif
106        static const char magic[]="Salted__";
107        char mbuf[sizeof magic-1];
108        char *strbuf=NULL;
109        unsigned char *buff=NULL,*bufsize=NULL;
110        int bsize=BSIZE,verbose=0;
111        int ret=1,inl;
112        int nopad = 0;
113        unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
114        unsigned char salt[PKCS5_SALT_LEN];
115        char *str=NULL, *passarg = NULL, *pass = NULL;
116        char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
117        int enc=1,printkey=0,i,base64=0;
118        int debug=0,olb64=0,nosalt=0;
119        const EVP_CIPHER *cipher=NULL,*c;
120        char *inf=NULL,*outf=NULL;
121        BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL;
122#define PROG_NAME_SIZE  39
123        char pname[PROG_NAME_SIZE+1];
124#ifndef OPENSSL_NO_ENGINE
125        char *engine = NULL;
126#endif
127
128        apps_startup();
129
130        if (bio_err == NULL)
131                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
132                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
133
134        if (!load_config(bio_err, NULL))
135                goto end;
136
137        /* first check the program name */
138        program_name(argv[0],pname,sizeof pname);
139        if (strcmp(pname,"base64") == 0)
140                base64=1;
141
142        cipher=EVP_get_cipherbyname(pname);
143        if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0))
144                {
145                BIO_printf(bio_err,"%s is an unknown cipher\n",pname);
146                goto bad;
147                }
148
149        argc--;
150        argv++;
151        while (argc >= 1)
152                {
153                if      (strcmp(*argv,"-e") == 0)
154                        enc=1;
155                else if (strcmp(*argv,"-in") == 0)
156                        {
157                        if (--argc < 1) goto bad;
158                        inf= *(++argv);
159                        }
160                else if (strcmp(*argv,"-out") == 0)
161                        {
162                        if (--argc < 1) goto bad;
163                        outf= *(++argv);
164                        }
165                else if (strcmp(*argv,"-pass") == 0)
166                        {
167                        if (--argc < 1) goto bad;
168                        passarg= *(++argv);
169                        }
170#ifndef OPENSSL_NO_ENGINE
171                else if (strcmp(*argv,"-engine") == 0)
172                        {
173                        if (--argc < 1) goto bad;
174                        engine= *(++argv);
175                        }
176#endif
177                else if (strcmp(*argv,"-d") == 0)
178                        enc=0;
179                else if (strcmp(*argv,"-p") == 0)
180                        printkey=1;
181                else if (strcmp(*argv,"-v") == 0)
182                        verbose=1;
183                else if (strcmp(*argv,"-nopad") == 0)
184                        nopad=1;
185                else if (strcmp(*argv,"-salt") == 0)
186                        nosalt=0;
187                else if (strcmp(*argv,"-nosalt") == 0)
188                        nosalt=1;
189                else if (strcmp(*argv,"-debug") == 0)
190                        debug=1;
191                else if (strcmp(*argv,"-P") == 0)
192                        printkey=2;
193                else if (strcmp(*argv,"-A") == 0)
194                        olb64=1;
195                else if (strcmp(*argv,"-a") == 0)
196                        base64=1;
197                else if (strcmp(*argv,"-base64") == 0)
198                        base64=1;
199                else if (strcmp(*argv,"-bufsize") == 0)
200                        {
201                        if (--argc < 1) goto bad;
202                        bufsize=(unsigned char *)*(++argv);
203                        }
204                else if (strcmp(*argv,"-k") == 0)
205                        {
206                        if (--argc < 1) goto bad;
207                        str= *(++argv);
208                        }
209                else if (strcmp(*argv,"-kfile") == 0)
210                        {
211                        static char buf[128];
212                        FILE *infile;
213                        char *file;
214
215                        if (--argc < 1) goto bad;
216                        file= *(++argv);
217                        infile=fopen(file,"r");
218                        if (infile == NULL)
219                                {
220                                BIO_printf(bio_err,"unable to read key from '%s'\n",
221                                        file);
222                                goto bad;
223                                }
224                        buf[0]='\0';
225                        fgets(buf,sizeof buf,infile);
226                        fclose(infile);
227                        i=strlen(buf);
228                        if ((i > 0) &&
229                                ((buf[i-1] == '\n') || (buf[i-1] == '\r')))
230                                buf[--i]='\0';
231                        if ((i > 0) &&
232                                ((buf[i-1] == '\n') || (buf[i-1] == '\r')))
233                                buf[--i]='\0';
234                        if (i < 1)
235                                {
236                                BIO_printf(bio_err,"zero length password\n");
237                                goto bad;
238                                }
239                        str=buf;
240                        }
241                else if (strcmp(*argv,"-K") == 0)
242                        {
243                        if (--argc < 1) goto bad;
244                        hkey= *(++argv);
245                        }
246                else if (strcmp(*argv,"-S") == 0)
247                        {
248                        if (--argc < 1) goto bad;
249                        hsalt= *(++argv);
250                        }
251                else if (strcmp(*argv,"-iv") == 0)
252                        {
253                        if (--argc < 1) goto bad;
254                        hiv= *(++argv);
255                        }
256                else if ((argv[0][0] == '-') &&
257                        ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL))
258                        {
259                        cipher=c;
260                        }
261                else if (strcmp(*argv,"-none") == 0)
262                        cipher=NULL;
263                else
264                        {
265                        BIO_printf(bio_err,"unknown option '%s'\n",*argv);
266bad:
267                        BIO_printf(bio_err,"options are\n");
268                        BIO_printf(bio_err,"%-14s input file\n","-in <file>");
269                        BIO_printf(bio_err,"%-14s output file\n","-out <file>");
270                        BIO_printf(bio_err,"%-14s pass phrase source\n","-pass <arg>");
271                        BIO_printf(bio_err,"%-14s encrypt\n","-e");
272                        BIO_printf(bio_err,"%-14s decrypt\n","-d");
273                        BIO_printf(bio_err,"%-14s base64 encode/decode, depending on encryption flag\n","-a/-base64");
274                        BIO_printf(bio_err,"%-14s key is the next argument\n","-k");
275                        BIO_printf(bio_err,"%-14s key is the first line of the file argument\n","-kfile");
276                        BIO_printf(bio_err,"%-14s key/iv in hex is the next argument\n","-K/-iv");
277                        BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]");
278                        BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>");
279#ifndef OPENSSL_NO_ENGINE
280                        BIO_printf(bio_err,"%-14s use engine e, possibly a hardware device.\n","-engine e");
281#endif
282
283                        BIO_printf(bio_err,"Cipher Types\n");
284                        OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
285                                               show_ciphers,
286                                               bio_err);
287                        BIO_printf(bio_err,"\n");
288
289                        goto end;
290                        }
291                argc--;
292                argv++;
293                }
294
295#ifndef OPENSSL_NO_ENGINE
296        e = setup_engine(bio_err, engine, 0);
297#endif
298
299        if (bufsize != NULL)
300                {
301                unsigned long n;
302
303                for (n=0; *bufsize; bufsize++)
304                        {
305                        i= *bufsize;
306                        if ((i <= '9') && (i >= '0'))
307                                n=n*10+i-'0';
308                        else if (i == 'k')
309                                {
310                                n*=1024;
311                                bufsize++;
312                                break;
313                                }
314                        }
315                if (*bufsize != '\0')
316                        {
317                        BIO_printf(bio_err,"invalid 'bufsize' specified.\n");
318                        goto end;
319                        }
320
321                /* It must be large enough for a base64 encoded line */
322                if (n < 80) n=80;
323
324                bsize=(int)n;
325                if (verbose) BIO_printf(bio_err,"bufsize=%d\n",bsize);
326                }
327
328        strbuf=OPENSSL_malloc(SIZE);
329        buff=(unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize));
330        if ((buff == NULL) || (strbuf == NULL))
331                {
332                BIO_printf(bio_err,"OPENSSL_malloc failure %ld\n",(long)EVP_ENCODE_LENGTH(bsize));
333                goto end;
334                }
335
336        in=BIO_new(BIO_s_file());
337        out=BIO_new(BIO_s_file());
338        if ((in == NULL) || (out == NULL))
339                {
340                ERR_print_errors(bio_err);
341                goto end;
342                }
343        if (debug)
344                {
345                BIO_set_callback(in,BIO_debug_callback);
346                BIO_set_callback(out,BIO_debug_callback);
347                BIO_set_callback_arg(in,bio_err);
348                BIO_set_callback_arg(out,bio_err);
349                }
350
351        if (inf == NULL)
352                BIO_set_fp(in,stdin,BIO_NOCLOSE);
353        else
354                {
355                if (BIO_read_filename(in,inf) <= 0)
356                        {
357                        perror(inf);
358                        goto end;
359                        }
360                }
361
362        if(!str && passarg) {
363                if(!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
364                        BIO_printf(bio_err, "Error getting password\n");
365                        goto end;
366                }
367                str = pass;
368        }
369
370        if ((str == NULL) && (cipher != NULL) && (hkey == NULL))
371                {
372                for (;;)
373                        {
374                        char buf[200];
375
376                        sprintf(buf,"enter %s %s password:",
377                                OBJ_nid2ln(EVP_CIPHER_nid(cipher)),
378                                (enc)?"encryption":"decryption");
379                        strbuf[0]='\0';
380                        i=EVP_read_pw_string((char *)strbuf,SIZE,buf,enc);
381                        if (i == 0)
382                                {
383                                if (strbuf[0] == '\0')
384                                        {
385                                        ret=1;
386                                        goto end;
387                                        }
388                                str=strbuf;
389                                break;
390                                }
391                        if (i < 0)
392                                {
393                                BIO_printf(bio_err,"bad password read\n");
394                                goto end;
395                                }
396                        }
397                }
398
399
400        if (outf == NULL)
401                {
402                BIO_set_fp(out,stdout,BIO_NOCLOSE);
403#ifdef OPENSSL_SYS_VMS
404                {
405                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
406                out = BIO_push(tmpbio, out);
407                }
408#endif
409                }
410        else
411                {
412                if (BIO_write_filename(out,outf) <= 0)
413                        {
414                        perror(outf);
415                        goto end;
416                        }
417                }
418
419        rbio=in;
420        wbio=out;
421
422        if (base64)
423                {
424                if ((b64=BIO_new(BIO_f_base64())) == NULL)
425                        goto end;
426                if (debug)
427                        {
428                        BIO_set_callback(b64,BIO_debug_callback);
429                        BIO_set_callback_arg(b64,bio_err);
430                        }
431                if (olb64)
432                        BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
433                if (enc)
434                        wbio=BIO_push(b64,wbio);
435                else
436                        rbio=BIO_push(b64,rbio);
437                }
438
439        if (cipher != NULL)
440                {
441                /* Note that str is NULL if a key was passed on the command
442                 * line, so we get no salt in that case. Is this a bug?
443                 */
444                if (str != NULL)
445                        {
446                        /* Salt handling: if encrypting generate a salt and
447                         * write to output BIO. If decrypting read salt from
448                         * input BIO.
449                         */
450                        unsigned char *sptr;
451                        if(nosalt) sptr = NULL;
452                        else {
453                                if(enc) {
454                                        if(hsalt) {
455                                                if(!set_hex(hsalt,salt,sizeof salt)) {
456                                                        BIO_printf(bio_err,
457                                                                "invalid hex salt value\n");
458                                                        goto end;
459                                                }
460                                        } else if (RAND_pseudo_bytes(salt, sizeof salt) < 0)
461                                                goto end;
462                                        /* If -P option then don't bother writing */
463                                        if((printkey != 2)
464                                           && (BIO_write(wbio,magic,
465                                                         sizeof magic-1) != sizeof magic-1
466                                               || BIO_write(wbio,
467                                                            (char *)salt,
468                                                            sizeof salt) != sizeof salt)) {
469                                                BIO_printf(bio_err,"error writing output file\n");
470                                                goto end;
471                                        }
472                                } else if(BIO_read(rbio,mbuf,sizeof mbuf) != sizeof mbuf
473                                          || BIO_read(rbio,
474                                                      (unsigned char *)salt,
475                                    sizeof salt) != sizeof salt) {
476                                        BIO_printf(bio_err,"error reading input file\n");
477                                        goto end;
478                                } else if(memcmp(mbuf,magic,sizeof magic-1)) {
479                                    BIO_printf(bio_err,"bad magic number\n");
480                                    goto end;
481                                }
482
483                                sptr = salt;
484                        }
485
486                        EVP_BytesToKey(cipher,EVP_md5(),sptr,
487                                (unsigned char *)str,
488                                strlen(str),1,key,iv);
489                        /* zero the complete buffer or the string
490                         * passed from the command line
491                         * bug picked up by
492                         * Larry J. Hughes Jr. <hughes@indiana.edu> */
493                        if (str == strbuf)
494                                OPENSSL_cleanse(str,SIZE);
495                        else
496                                OPENSSL_cleanse(str,strlen(str));
497                        }
498                if ((hiv != NULL) && !set_hex(hiv,iv,sizeof iv))
499                        {
500                        BIO_printf(bio_err,"invalid hex iv value\n");
501                        goto end;
502                        }
503                if ((hiv == NULL) && (str == NULL))
504                        {
505                        /* No IV was explicitly set and no IV was generated
506                         * during EVP_BytesToKey. Hence the IV is undefined,
507                         * making correct decryption impossible. */
508                        BIO_printf(bio_err, "iv undefined\n");
509                        goto end;
510                        }
511                if ((hkey != NULL) && !set_hex(hkey,key,sizeof key))
512                        {
513                        BIO_printf(bio_err,"invalid hex key value\n");
514                        goto end;
515                        }
516
517                if ((benc=BIO_new(BIO_f_cipher())) == NULL)
518                        goto end;
519                BIO_set_cipher(benc,cipher,key,iv,enc);
520                if (nopad)
521                        {
522                        EVP_CIPHER_CTX *ctx;
523                        BIO_get_cipher_ctx(benc, &ctx);
524                        EVP_CIPHER_CTX_set_padding(ctx, 0);
525                        }
526                if (debug)
527                        {
528                        BIO_set_callback(benc,BIO_debug_callback);
529                        BIO_set_callback_arg(benc,bio_err);
530                        }
531
532                if (printkey)
533                        {
534                        if (!nosalt)
535                                {
536                                printf("salt=");
537                                for (i=0; i<sizeof salt; i++)
538                                        printf("%02X",salt[i]);
539                                printf("\n");
540                                }
541                        if (cipher->key_len > 0)
542                                {
543                                printf("key=");
544                                for (i=0; i<cipher->key_len; i++)
545                                        printf("%02X",key[i]);
546                                printf("\n");
547                                }
548                        if (cipher->iv_len > 0)
549                                {
550                                printf("iv =");
551                                for (i=0; i<cipher->iv_len; i++)
552                                        printf("%02X",iv[i]);
553                                printf("\n");
554                                }
555                        if (printkey == 2)
556                                {
557                                ret=0;
558                                goto end;
559                                }
560                        }
561                }
562
563        /* Only encrypt/decrypt as we write the file */
564        if (benc != NULL)
565                wbio=BIO_push(benc,wbio);
566
567        for (;;)
568                {
569                inl=BIO_read(rbio,(char *)buff,bsize);
570                if (inl <= 0) break;
571                if (BIO_write(wbio,(char *)buff,inl) != inl)
572                        {
573                        BIO_printf(bio_err,"error writing output file\n");
574                        goto end;
575                        }
576                }
577        if (!BIO_flush(wbio))
578                {
579                BIO_printf(bio_err,"bad decrypt\n");
580                goto end;
581                }
582
583        ret=0;
584        if (verbose)
585                {
586                BIO_printf(bio_err,"bytes read   :%8ld\n",BIO_number_read(in));
587                BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out));
588                }
589end:
590        ERR_print_errors(bio_err);
591        if (strbuf != NULL) OPENSSL_free(strbuf);
592        if (buff != NULL) OPENSSL_free(buff);
593        if (in != NULL) BIO_free(in);
594        if (out != NULL) BIO_free_all(out);
595        if (benc != NULL) BIO_free(benc);
596        if (b64 != NULL) BIO_free(b64);
597        if(pass) OPENSSL_free(pass);
598        apps_shutdown();
599        OPENSSL_EXIT(ret);
600        }
601
602int set_hex(char *in, unsigned char *out, int size)
603        {
604        int i,n;
605        unsigned char j;
606
607        n=strlen(in);
608        if (n > (size*2))
609                {
610                BIO_printf(bio_err,"hex string is too long\n");
611                return(0);
612                }
613        memset(out,0,size);
614        for (i=0; i<n; i++)
615                {
616                j=(unsigned char)*in;
617                *(in++)='\0';
618                if (j == 0) break;
619                if ((j >= '0') && (j <= '9'))
620                        j-='0';
621                else if ((j >= 'A') && (j <= 'F'))
622                        j=j-'A'+10;
623                else if ((j >= 'a') && (j <= 'f'))
624                        j=j-'a'+10;
625                else
626                        {
627                        BIO_printf(bio_err,"non-hex digit\n");
628                        return(0);
629                        }
630                if (i&1)
631                        out[i/2]|=j;
632                else
633                        out[i/2]=(j<<4);
634                }
635        return(1);
636        }
Note: See TracBrowser for help on using the repository browser.