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

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