ssl/libcrypto/src/crypto/des/des.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* crypto/des/des.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 <openssl/opensslconf.h>
       
    63 #ifndef OPENSSL_SYS_MSDOS
       
    64 #ifndef OPENSSL_SYS_VMS
       
    65 #include OPENSSL_UNISTD
       
    66 #else /* OPENSSL_SYS_VMS */
       
    67 #ifdef __DECC
       
    68 #include <unistd.h>
       
    69 #else /* not __DECC */
       
    70 #include <math.h>
       
    71 #endif /* __DECC */
       
    72 #endif /* OPENSSL_SYS_VMS */
       
    73 #else /* OPENSSL_SYS_MSDOS */
       
    74 #include <io.h>
       
    75 #endif
       
    76 
       
    77 #include <time.h>
       
    78 #include "des_ver.h"
       
    79 
       
    80 #ifdef OPENSSL_SYS_VMS
       
    81 #include <types.h>
       
    82 #include <stat.h>
       
    83 #else
       
    84 #ifndef _IRIX
       
    85 #include <sys/types.h>
       
    86 #endif
       
    87 #include <sys/stat.h>
       
    88 #endif
       
    89 #include <openssl/des.h>
       
    90 #include <openssl/rand.h>
       
    91 #include <openssl/ui_compat.h>
       
    92 
       
    93 void usage(void);
       
    94 void doencryption(void);
       
    95 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
       
    96 void uufwriteEnd(FILE *fp);
       
    97 int uufread(unsigned char *out,int size,unsigned int num,FILE *fp);
       
    98 int uuencode(unsigned char *in,int num,unsigned char *out);
       
    99 int uudecode(unsigned char *in,int num,unsigned char *out);
       
   100 void DES_3cbc_encrypt(DES_cblock *input,DES_cblock *output,long length,
       
   101 	DES_key_schedule sk1,DES_key_schedule sk2,
       
   102 	DES_cblock *ivec1,DES_cblock *ivec2,int enc);
       
   103 #ifdef OPENSSL_SYS_VMS
       
   104 #define EXIT(a) exit(a&0x10000000L)
       
   105 #else
       
   106 #define EXIT(a) exit(a)
       
   107 #endif
       
   108 
       
   109 #define BUFSIZE (8*1024)
       
   110 #define VERIFY  1
       
   111 #define KEYSIZ	8
       
   112 #define KEYSIZB 1024 /* should hit tty line limit first :-) */
       
   113 char key[KEYSIZB+1];
       
   114 int do_encrypt,longk=0;
       
   115 FILE *DES_IN,*DES_OUT,*CKSUM_OUT;
       
   116 char uuname[200];
       
   117 unsigned char uubuf[50];
       
   118 int uubufnum=0;
       
   119 #define INUUBUFN	(45*100)
       
   120 #define OUTUUBUF	(65*100)
       
   121 unsigned char b[OUTUUBUF];
       
   122 unsigned char bb[300];
       
   123 DES_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
       
   124 char cksumname[200]="";
       
   125 
       
   126 int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error;
       
   127 
       
   128 int main(int argc, char **argv)
       
   129 	{
       
   130 	int i;
       
   131 	struct stat ins,outs;
       
   132 	char *p;
       
   133 	char *in=NULL,*out=NULL;
       
   134 
       
   135 	vflag=cflag=eflag=dflag=kflag=hflag=bflag=fflag=sflag=uflag=flag3=0;
       
   136 	error=0;
       
   137 	memset(key,0,sizeof(key));
       
   138 
       
   139 	for (i=1; i<argc; i++)
       
   140 		{
       
   141 		p=argv[i];
       
   142 		if ((p[0] == '-') && (p[1] != '\0'))
       
   143 			{
       
   144 			p++;
       
   145 			while (*p)
       
   146 				{
       
   147 				switch (*(p++))
       
   148 					{
       
   149 				case '3':
       
   150 					flag3=1;
       
   151 					longk=1;
       
   152 					break;
       
   153 				case 'c':
       
   154 					cflag=1;
       
   155 					strncpy(cksumname,p,200);
       
   156 					cksumname[sizeof(cksumname)-1]='\0';
       
   157 					p+=strlen(cksumname);
       
   158 					break;
       
   159 				case 'C':
       
   160 					cflag=1;
       
   161 					longk=1;
       
   162 					strncpy(cksumname,p,200);
       
   163 					cksumname[sizeof(cksumname)-1]='\0';
       
   164 					p+=strlen(cksumname);
       
   165 					break;
       
   166 				case 'e':
       
   167 					eflag=1;
       
   168 					break;
       
   169 				case 'v':
       
   170 					vflag=1;
       
   171 					break;
       
   172 				case 'E':
       
   173 					eflag=1;
       
   174 					longk=1;
       
   175 					break;
       
   176 				case 'd':
       
   177 					dflag=1;
       
   178 					break;
       
   179 				case 'D':
       
   180 					dflag=1;
       
   181 					longk=1;
       
   182 					break;
       
   183 				case 'b':
       
   184 					bflag=1;
       
   185 					break;
       
   186 				case 'f':
       
   187 					fflag=1;
       
   188 					break;
       
   189 				case 's':
       
   190 					sflag=1;
       
   191 					break;
       
   192 				case 'u':
       
   193 					uflag=1;
       
   194 					strncpy(uuname,p,200);
       
   195 					uuname[sizeof(uuname)-1]='\0';
       
   196 					p+=strlen(uuname);
       
   197 					break;
       
   198 				case 'h':
       
   199 					hflag=1;
       
   200 					break;
       
   201 				case 'k':
       
   202 					kflag=1;
       
   203 					if ((i+1) == argc)
       
   204 						{
       
   205 						fputs("must have a key with the -k option\n",stderr);
       
   206 						error=1;
       
   207 						}
       
   208 					else
       
   209 						{
       
   210 						int j;
       
   211 
       
   212 						i++;
       
   213 						strncpy(key,argv[i],KEYSIZB);
       
   214 						for (j=strlen(argv[i])-1; j>=0; j--)
       
   215 							argv[i][j]='\0';
       
   216 						}
       
   217 					break;
       
   218 				default:
       
   219 					fprintf(stderr,"'%c' unknown flag\n",p[-1]);
       
   220 					error=1;
       
   221 					break;
       
   222 					}
       
   223 				}
       
   224 			}
       
   225 		else
       
   226 			{
       
   227 			if (in == NULL)
       
   228 				in=argv[i];
       
   229 			else if (out == NULL)
       
   230 				out=argv[i];
       
   231 			else
       
   232 				error=1;
       
   233 			}
       
   234 		}
       
   235 	if (error) usage();
       
   236 	/* We either
       
   237 	 * do checksum or
       
   238 	 * do encrypt or
       
   239 	 * do decrypt or
       
   240 	 * do decrypt then ckecksum or
       
   241 	 * do checksum then encrypt
       
   242 	 */
       
   243 	if (((eflag+dflag) == 1) || cflag)
       
   244 		{
       
   245 		if (eflag) do_encrypt=DES_ENCRYPT;
       
   246 		if (dflag) do_encrypt=DES_DECRYPT;
       
   247 		}
       
   248 	else
       
   249 		{
       
   250 		if (vflag) 
       
   251 			{
       
   252 #ifndef _Windows			
       
   253 			fprintf(stderr,"des(1) built with %s\n",libdes_version);
       
   254 #endif			
       
   255 			EXIT(1);
       
   256 			}
       
   257 		else usage();
       
   258 		}
       
   259 
       
   260 #ifndef _Windows			
       
   261 	if (vflag) fprintf(stderr,"des(1) built with %s\n",libdes_version);
       
   262 #endif			
       
   263 	if (	(in != NULL) &&
       
   264 		(out != NULL) &&
       
   265 #ifndef OPENSSL_SYS_MSDOS
       
   266 		(stat(in,&ins) != -1) &&
       
   267 		(stat(out,&outs) != -1) &&
       
   268 		(ins.st_dev == outs.st_dev) &&
       
   269 		(ins.st_ino == outs.st_ino))
       
   270 #else /* OPENSSL_SYS_MSDOS */
       
   271 		(strcmp(in,out) == 0))
       
   272 #endif
       
   273 			{
       
   274 			fputs("input and output file are the same\n",stderr);
       
   275 			EXIT(3);
       
   276 			}
       
   277 
       
   278 	if (!kflag)
       
   279 		if (des_read_pw_string(key,KEYSIZB+1,"Enter key:",eflag?VERIFY:0))
       
   280 			{
       
   281 			fputs("password error\n",stderr);
       
   282 			EXIT(2);
       
   283 			}
       
   284 
       
   285 	if (in == NULL)
       
   286 		DES_IN=stdin;
       
   287 	else if ((DES_IN=fopen(in,"r")) == NULL)
       
   288 		{
       
   289 		perror("opening input file");
       
   290 		EXIT(4);
       
   291 		}
       
   292 
       
   293 	CKSUM_OUT=stdout;
       
   294 	if (out == NULL)
       
   295 		{
       
   296 		DES_OUT=stdout;
       
   297 		CKSUM_OUT=stderr;
       
   298 		}
       
   299 	else if ((DES_OUT=fopen(out,"w")) == NULL)
       
   300 		{
       
   301 		perror("opening output file");
       
   302 		EXIT(5);
       
   303 		}
       
   304 
       
   305 #ifdef OPENSSL_SYS_MSDOS
       
   306 	/* This should set the file to binary mode. */
       
   307 	{
       
   308 #include <fcntl.h>
       
   309 	if (!(uflag && dflag))
       
   310 		setmode(fileno(DES_IN),O_BINARY);
       
   311 	if (!(uflag && eflag))
       
   312 		setmode(fileno(DES_OUT),O_BINARY);
       
   313 	}
       
   314 #endif
       
   315 
       
   316 	doencryption();
       
   317 	fclose(DES_IN);
       
   318 	fclose(DES_OUT);
       
   319 	EXIT(0);
       
   320 	}
       
   321 
       
   322 void usage(void)
       
   323 	{
       
   324 	char **u;
       
   325 	static const char *Usage[]={
       
   326 "des <options> [input-file [output-file]]",
       
   327 "options:",
       
   328 "-v         : des(1) version number",
       
   329 "-e         : encrypt using SunOS compatible user key to DES key conversion.",
       
   330 "-E         : encrypt ",
       
   331 "-d         : decrypt using SunOS compatible user key to DES key conversion.",
       
   332 "-D         : decrypt ",
       
   333 "-c[ckname] : generate a cbc_cksum using SunOS compatible user key to",
       
   334 "             DES key conversion and output to ckname (stdout default,",
       
   335 "             stderr if data being output on stdout).  The checksum is",
       
   336 "             generated before encryption and after decryption if used",
       
   337 "             in conjunction with -[eEdD].",
       
   338 "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].",
       
   339 "-k key     : use key 'key'",
       
   340 "-h         : the key that is entered will be a hexadecimal number",
       
   341 "             that is used directly as the des key",
       
   342 "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]",
       
   343 "             (uuname is the filename to put in the uuencode header).",
       
   344 "-b         : encrypt using DES in ecb encryption mode, the default is cbc mode.",
       
   345 "-3         : encrypt using triple DES encryption.  This uses 2 keys",
       
   346 "             generated from the input key.  If the input key is less",
       
   347 "             than 8 characters long, this is equivalent to normal",
       
   348 "             encryption.  Default is triple cbc, -b makes it triple ecb.",
       
   349 NULL
       
   350 };
       
   351 	for (u=(char **)Usage; *u; u++)
       
   352 		{
       
   353 		fputs(*u,stderr);
       
   354 		fputc('\n',stderr);
       
   355 		}
       
   356 
       
   357 	EXIT(1);
       
   358 	}
       
   359 
       
   360 void doencryption(void)
       
   361 	{
       
   362 #ifdef _LIBC
       
   363 	extern unsigned long time();
       
   364 #endif
       
   365 
       
   366 	register int i;
       
   367 	DES_key_schedule ks,ks2;
       
   368 	DES_cblock iv,iv2;
       
   369 	char *p;
       
   370 	int num=0,j,k,l,rem,ll,len,last,ex=0;
       
   371 	DES_cblock kk,k2;
       
   372 	FILE *O;
       
   373 	int Exit=0;
       
   374 #ifndef OPENSSL_SYS_MSDOS
       
   375 	static unsigned char buf[BUFSIZE+8],obuf[BUFSIZE+8];
       
   376 #else
       
   377 	static unsigned char *buf=NULL,*obuf=NULL;
       
   378 
       
   379 	if (buf == NULL)
       
   380 		{
       
   381 		if (    (( buf=OPENSSL_malloc(BUFSIZE+8)) == NULL) ||
       
   382 			((obuf=OPENSSL_malloc(BUFSIZE+8)) == NULL))
       
   383 			{
       
   384 			fputs("Not enough memory\n",stderr);
       
   385 			Exit=10;
       
   386 			goto problems;
       
   387 			}
       
   388 		}
       
   389 #endif
       
   390 
       
   391 	if (hflag)
       
   392 		{
       
   393 		j=(flag3?16:8);
       
   394 		p=key;
       
   395 		for (i=0; i<j; i++)
       
   396 			{
       
   397 			k=0;
       
   398 			if ((*p <= '9') && (*p >= '0'))
       
   399 				k=(*p-'0')<<4;
       
   400 			else if ((*p <= 'f') && (*p >= 'a'))
       
   401 				k=(*p-'a'+10)<<4;
       
   402 			else if ((*p <= 'F') && (*p >= 'A'))
       
   403 				k=(*p-'A'+10)<<4;
       
   404 			else
       
   405 				{
       
   406 				fputs("Bad hex key\n",stderr);
       
   407 				Exit=9;
       
   408 				goto problems;
       
   409 				}
       
   410 			p++;
       
   411 			if ((*p <= '9') && (*p >= '0'))
       
   412 				k|=(*p-'0');
       
   413 			else if ((*p <= 'f') && (*p >= 'a'))
       
   414 				k|=(*p-'a'+10);
       
   415 			else if ((*p <= 'F') && (*p >= 'A'))
       
   416 				k|=(*p-'A'+10);
       
   417 			else
       
   418 				{
       
   419 				fputs("Bad hex key\n",stderr);
       
   420 				Exit=9;
       
   421 				goto problems;
       
   422 				}
       
   423 			p++;
       
   424 			if (i < 8)
       
   425 				kk[i]=k;
       
   426 			else
       
   427 				k2[i-8]=k;
       
   428 			}
       
   429 		DES_set_key_unchecked(&k2,&ks2);
       
   430 		OPENSSL_cleanse(k2,sizeof(k2));
       
   431 		}
       
   432 	else if (longk || flag3)
       
   433 		{
       
   434 		if (flag3)
       
   435 			{
       
   436 			DES_string_to_2keys(key,&kk,&k2);
       
   437 			DES_set_key_unchecked(&k2,&ks2);
       
   438 			OPENSSL_cleanse(k2,sizeof(k2));
       
   439 			}
       
   440 		else
       
   441 			DES_string_to_key(key,&kk);
       
   442 		}
       
   443 	else
       
   444 		for (i=0; i<KEYSIZ; i++)
       
   445 			{
       
   446 			l=0;
       
   447 			k=key[i];
       
   448 			for (j=0; j<8; j++)
       
   449 				{
       
   450 				if (k&1) l++;
       
   451 				k>>=1;
       
   452 				}
       
   453 			if (l & 1)
       
   454 				kk[i]=key[i]&0x7f;
       
   455 			else
       
   456 				kk[i]=key[i]|0x80;
       
   457 			}
       
   458 
       
   459 	DES_set_key_unchecked(&kk,&ks);
       
   460 	OPENSSL_cleanse(key,sizeof(key));
       
   461 	OPENSSL_cleanse(kk,sizeof(kk));
       
   462 	/* woops - A bug that does not showup under unix :-( */
       
   463 	memset(iv,0,sizeof(iv));
       
   464 	memset(iv2,0,sizeof(iv2));
       
   465 
       
   466 	l=1;
       
   467 	rem=0;
       
   468 	/* first read */
       
   469 	if (eflag || (!dflag && cflag))
       
   470 		{
       
   471 		for (;;)
       
   472 			{
       
   473 			num=l=fread(&(buf[rem]),1,BUFSIZE,DES_IN);
       
   474 			l+=rem;
       
   475 			num+=rem;
       
   476 			if (l < 0)
       
   477 				{
       
   478 				perror("read error");
       
   479 				Exit=6;
       
   480 				goto problems;
       
   481 				}
       
   482 
       
   483 			rem=l%8;
       
   484 			len=l-rem;
       
   485 			if (feof(DES_IN))
       
   486 				{
       
   487 				for (i=7-rem; i>0; i--)
       
   488 					RAND_pseudo_bytes(buf + l++, 1);
       
   489 				buf[l++]=rem;
       
   490 				ex=1;
       
   491 				len+=rem;
       
   492 				}
       
   493 			else
       
   494 				l-=rem;
       
   495 
       
   496 			if (cflag)
       
   497 				{
       
   498 				DES_cbc_cksum(buf,&cksum,
       
   499 					(long)len,&ks,&cksum);
       
   500 				if (!eflag)
       
   501 					{
       
   502 					if (feof(DES_IN)) break;
       
   503 					else continue;
       
   504 					}
       
   505 				}
       
   506 
       
   507 			if (bflag && !flag3)
       
   508 				for (i=0; i<l; i+=8)
       
   509 					DES_ecb_encrypt(
       
   510 						(DES_cblock *)&(buf[i]),
       
   511 						(DES_cblock *)&(obuf[i]),
       
   512 						&ks,do_encrypt);
       
   513 			else if (flag3 && bflag)
       
   514 				for (i=0; i<l; i+=8)
       
   515 					DES_ecb2_encrypt(
       
   516 						(DES_cblock *)&(buf[i]),
       
   517 						(DES_cblock *)&(obuf[i]),
       
   518 						&ks,&ks2,do_encrypt);
       
   519 			else if (flag3 && !bflag)
       
   520 				{
       
   521 				char tmpbuf[8];
       
   522 
       
   523 				if (rem) memcpy(tmpbuf,&(buf[l]),
       
   524 					(unsigned int)rem);
       
   525 				DES_3cbc_encrypt(
       
   526 					(DES_cblock *)buf,(DES_cblock *)obuf,
       
   527 					(long)l,ks,ks2,&iv,
       
   528 					&iv2,do_encrypt);
       
   529 				if (rem) memcpy(&(buf[l]),tmpbuf,
       
   530 					(unsigned int)rem);
       
   531 				}
       
   532 			else
       
   533 				{
       
   534 				DES_cbc_encrypt(
       
   535 					buf,obuf,
       
   536 					(long)l,&ks,&iv,do_encrypt);
       
   537 				if (l >= 8) memcpy(iv,&(obuf[l-8]),8);
       
   538 				}
       
   539 			if (rem) memcpy(buf,&(buf[l]),(unsigned int)rem);
       
   540 
       
   541 			i=0;
       
   542 			while (i < l)
       
   543 				{
       
   544 				if (uflag)
       
   545 					j=uufwrite(obuf,1,(unsigned int)l-i,
       
   546 						DES_OUT);
       
   547 				else
       
   548 					j=fwrite(obuf,1,(unsigned int)l-i,
       
   549 						DES_OUT);
       
   550 				if (j == -1)
       
   551 					{
       
   552 					perror("Write error");
       
   553 					Exit=7;
       
   554 					goto problems;
       
   555 					}
       
   556 				i+=j;
       
   557 				}
       
   558 			if (feof(DES_IN))
       
   559 				{
       
   560 				if (uflag) uufwriteEnd(DES_OUT);
       
   561 				break;
       
   562 				}
       
   563 			}
       
   564 		}
       
   565 	else /* decrypt */
       
   566 		{
       
   567 		ex=1;
       
   568 		for (;;)
       
   569 			{
       
   570 			if (ex) {
       
   571 				if (uflag)
       
   572 					l=uufread(buf,1,BUFSIZE,DES_IN);
       
   573 				else
       
   574 					l=fread(buf,1,BUFSIZE,DES_IN);
       
   575 				ex=0;
       
   576 				rem=l%8;
       
   577 				l-=rem;
       
   578 				}
       
   579 			if (l < 0)
       
   580 				{
       
   581 				perror("read error");
       
   582 				Exit=6;
       
   583 				goto problems;
       
   584 				}
       
   585 
       
   586 			if (bflag && !flag3)
       
   587 				for (i=0; i<l; i+=8)
       
   588 					DES_ecb_encrypt(
       
   589 						(DES_cblock *)&(buf[i]),
       
   590 						(DES_cblock *)&(obuf[i]),
       
   591 						&ks,do_encrypt);
       
   592 			else if (flag3 && bflag)
       
   593 				for (i=0; i<l; i+=8)
       
   594 					DES_ecb2_encrypt(
       
   595 						(DES_cblock *)&(buf[i]),
       
   596 						(DES_cblock *)&(obuf[i]),
       
   597 						&ks,&ks2,do_encrypt);
       
   598 			else if (flag3 && !bflag)
       
   599 				{
       
   600 				DES_3cbc_encrypt(
       
   601 					(DES_cblock *)buf,(DES_cblock *)obuf,
       
   602 					(long)l,ks,ks2,&iv,
       
   603 					&iv2,do_encrypt);
       
   604 				}
       
   605 			else
       
   606 				{
       
   607 				DES_cbc_encrypt(
       
   608 					buf,obuf,
       
   609 				 	(long)l,&ks,&iv,do_encrypt);
       
   610 				if (l >= 8) memcpy(iv,&(buf[l-8]),8);
       
   611 				}
       
   612 
       
   613 			if (uflag)
       
   614 				ll=uufread(&(buf[rem]),1,BUFSIZE,DES_IN);
       
   615 			else
       
   616 				ll=fread(&(buf[rem]),1,BUFSIZE,DES_IN);
       
   617 			ll+=rem;
       
   618 			rem=ll%8;
       
   619 			ll-=rem;
       
   620 			if (feof(DES_IN) && (ll == 0))
       
   621 				{
       
   622 				last=obuf[l-1];
       
   623 
       
   624 				if ((last > 7) || (last < 0))
       
   625 					{
       
   626 					fputs("The file was not decrypted correctly.\n",
       
   627 						stderr);
       
   628 					Exit=8;
       
   629 					last=0;
       
   630 					}
       
   631 				l=l-8+last;
       
   632 				}
       
   633 			i=0;
       
   634 			if (cflag) DES_cbc_cksum(obuf,
       
   635 				(DES_cblock *)cksum,(long)l/8*8,&ks,
       
   636 				(DES_cblock *)cksum);
       
   637 			while (i != l)
       
   638 				{
       
   639 				j=fwrite(obuf,1,(unsigned int)l-i,DES_OUT);
       
   640 				if (j == -1)
       
   641 					{
       
   642 					perror("Write error");
       
   643 					Exit=7;
       
   644 					goto problems;
       
   645 					}
       
   646 				i+=j;
       
   647 				}
       
   648 			l=ll;
       
   649 			if ((l == 0) && feof(DES_IN)) break;
       
   650 			}
       
   651 		}
       
   652 	if (cflag)
       
   653 		{
       
   654 		l=0;
       
   655 		if (cksumname[0] != '\0')
       
   656 			{
       
   657 			if ((O=fopen(cksumname,"w")) != NULL)
       
   658 				{
       
   659 				CKSUM_OUT=O;
       
   660 				l=1;
       
   661 				}
       
   662 			}
       
   663 		for (i=0; i<8; i++)
       
   664 			fprintf(CKSUM_OUT,"%02X",cksum[i]);
       
   665 		fprintf(CKSUM_OUT,"\n");
       
   666 		if (l) fclose(CKSUM_OUT);
       
   667 		}
       
   668 problems:
       
   669 	OPENSSL_cleanse(buf,sizeof(buf));
       
   670 	OPENSSL_cleanse(obuf,sizeof(obuf));
       
   671 	OPENSSL_cleanse(&ks,sizeof(ks));
       
   672 	OPENSSL_cleanse(&ks2,sizeof(ks2));
       
   673 	OPENSSL_cleanse(iv,sizeof(iv));
       
   674 	OPENSSL_cleanse(iv2,sizeof(iv2));
       
   675 	OPENSSL_cleanse(kk,sizeof(kk));
       
   676 	OPENSSL_cleanse(k2,sizeof(k2));
       
   677 	OPENSSL_cleanse(uubuf,sizeof(uubuf));
       
   678 	OPENSSL_cleanse(b,sizeof(b));
       
   679 	OPENSSL_cleanse(bb,sizeof(bb));
       
   680 	OPENSSL_cleanse(cksum,sizeof(cksum));
       
   681 	if (Exit) EXIT(Exit);
       
   682 	}
       
   683 
       
   684 /*    We ignore this parameter but it should be > ~50 I believe    */
       
   685 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp)
       
   686 	{
       
   687 	int i,j,left,rem,ret=num;
       
   688 	static int start=1;
       
   689 
       
   690 	if (start)
       
   691 		{
       
   692 		fprintf(fp,"begin 600 %s\n",
       
   693 			(uuname[0] == '\0')?"text.d":uuname);
       
   694 		start=0;
       
   695 		}
       
   696 
       
   697 	if (uubufnum)
       
   698 		{
       
   699 		if (uubufnum+num < 45)
       
   700 			{
       
   701 			memcpy(&(uubuf[uubufnum]),data,(unsigned int)num);
       
   702 			uubufnum+=num;
       
   703 			return(num);
       
   704 			}
       
   705 		else
       
   706 			{
       
   707 			i=45-uubufnum;
       
   708 			memcpy(&(uubuf[uubufnum]),data,(unsigned int)i);
       
   709 			j=uuencode((unsigned char *)uubuf,45,b);
       
   710 			fwrite(b,1,(unsigned int)j,fp);
       
   711 			uubufnum=0;
       
   712 			data+=i;
       
   713 			num-=i;
       
   714 			}
       
   715 		}
       
   716 
       
   717 	for (i=0; i<(((int)num)-INUUBUFN); i+=INUUBUFN)
       
   718 		{
       
   719 		j=uuencode(&(data[i]),INUUBUFN,b);
       
   720 		fwrite(b,1,(unsigned int)j,fp);
       
   721 		}
       
   722 	rem=(num-i)%45;
       
   723 	left=(num-i-rem);
       
   724 	if (left)
       
   725 		{
       
   726 		j=uuencode(&(data[i]),left,b);
       
   727 		fwrite(b,1,(unsigned int)j,fp);
       
   728 		i+=left;
       
   729 		}
       
   730 	if (i != num)
       
   731 		{
       
   732 		memcpy(uubuf,&(data[i]),(unsigned int)rem);
       
   733 		uubufnum=rem;
       
   734 		}
       
   735 	return(ret);
       
   736 	}
       
   737 
       
   738 void uufwriteEnd(FILE *fp)
       
   739 	{
       
   740 	int j;
       
   741 	static const char *end=" \nend\n";
       
   742 
       
   743 	if (uubufnum != 0)
       
   744 		{
       
   745 		uubuf[uubufnum]='\0';
       
   746 		uubuf[uubufnum+1]='\0';
       
   747 		uubuf[uubufnum+2]='\0';
       
   748 		j=uuencode(uubuf,uubufnum,b);
       
   749 		fwrite(b,1,(unsigned int)j,fp);
       
   750 		}
       
   751 	fwrite(end,1,strlen(end),fp);
       
   752 	}
       
   753 
       
   754 /* int size:  should always be > ~ 60; I actually ignore this parameter :-)    */
       
   755 int uufread(unsigned char *out, int size, unsigned int num, FILE *fp)
       
   756 	{
       
   757 	int i,j,tot;
       
   758 	static int done=0;
       
   759 	static int valid=0;
       
   760 	static int start=1;
       
   761 
       
   762 	if (start)
       
   763 		{
       
   764 		for (;;)
       
   765 			{
       
   766 			b[0]='\0';
       
   767 			fgets((char *)b,300,fp);
       
   768 			if (b[0] == '\0')
       
   769 				{
       
   770 				fprintf(stderr,"no 'begin' found in uuencoded input\n");
       
   771 				return(-1);
       
   772 				}
       
   773 			if (strncmp((char *)b,"begin ",6) == 0) break;
       
   774 			}
       
   775 		start=0;
       
   776 		}
       
   777 	if (done) return(0);
       
   778 	tot=0;
       
   779 	if (valid)
       
   780 		{
       
   781 		memcpy(out,bb,(unsigned int)valid);
       
   782 		tot=valid;
       
   783 		valid=0;
       
   784 		}
       
   785 	for (;;)
       
   786 		{
       
   787 		b[0]='\0';
       
   788 		fgets((char *)b,300,fp);
       
   789 		if (b[0] == '\0') break;
       
   790 		i=strlen((char *)b);
       
   791 		if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd'))
       
   792 			{
       
   793 			done=1;
       
   794 			while (!feof(fp))
       
   795 				{
       
   796 				fgets((char *)b,300,fp);
       
   797 				}
       
   798 			break;
       
   799 			}
       
   800 		i=uudecode(b,i,bb);
       
   801 		if (i < 0) break;
       
   802 		if ((i+tot+8) > num)
       
   803 			{
       
   804 			/* num to copy to make it a multiple of 8 */
       
   805 			j=(num/8*8)-tot-8;
       
   806 			memcpy(&(out[tot]),bb,(unsigned int)j);
       
   807 			tot+=j;
       
   808 			memcpy(bb,&(bb[j]),(unsigned int)i-j);
       
   809 			valid=i-j;
       
   810 			break;
       
   811 			}
       
   812 		memcpy(&(out[tot]),bb,(unsigned int)i);
       
   813 		tot+=i;
       
   814 		}
       
   815 	return(tot);
       
   816 	}
       
   817 
       
   818 #define ccc2l(c,l)      (l =((DES_LONG)(*((c)++)))<<16, \
       
   819 			 l|=((DES_LONG)(*((c)++)))<< 8, \
       
   820 		 	 l|=((DES_LONG)(*((c)++))))
       
   821 
       
   822 #define l2ccc(l,c)      (*((c)++)=(unsigned char)(((l)>>16)&0xff), \
       
   823                     *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
       
   824                     *((c)++)=(unsigned char)(((l)    )&0xff))
       
   825 
       
   826 
       
   827 int uuencode(unsigned char *in, int num, unsigned char *out)
       
   828 	{
       
   829 	int j,i,n,tot=0;
       
   830 	DES_LONG l;
       
   831 	register unsigned char *p;
       
   832 	p=out;
       
   833 
       
   834 	for (j=0; j<num; j+=45)
       
   835 		{
       
   836 		if (j+45 > num)
       
   837 			i=(num-j);
       
   838 		else	i=45;
       
   839 		*(p++)=i+' ';
       
   840 		for (n=0; n<i; n+=3)
       
   841 			{
       
   842 			ccc2l(in,l);
       
   843 			*(p++)=((l>>18)&0x3f)+' ';
       
   844 			*(p++)=((l>>12)&0x3f)+' ';
       
   845 			*(p++)=((l>> 6)&0x3f)+' ';
       
   846 			*(p++)=((l    )&0x3f)+' ';
       
   847 			tot+=4;
       
   848 			}
       
   849 		*(p++)='\n';
       
   850 		tot+=2;
       
   851 		}
       
   852 	*p='\0';
       
   853 	l=0;
       
   854 	return(tot);
       
   855 	}
       
   856 
       
   857 int uudecode(unsigned char *in, int num, unsigned char *out)
       
   858 	{
       
   859 	int j,i,k;
       
   860 	unsigned int n=0,space=0;
       
   861 	DES_LONG l;
       
   862 	DES_LONG w,x,y,z;
       
   863 	unsigned int blank=(unsigned int)'\n'-' ';
       
   864 
       
   865 	for (j=0; j<num; )
       
   866 		{
       
   867 		n= *(in++)-' ';
       
   868 		if (n == blank)
       
   869 			{
       
   870 			n=0;
       
   871 			in--;
       
   872 			}
       
   873 		if (n > 60)
       
   874 			{
       
   875 			fprintf(stderr,"uuencoded line length too long\n");
       
   876 			return(-1);
       
   877 			}
       
   878 		j++;
       
   879 
       
   880 		for (i=0; i<n; j+=4,i+=3)
       
   881 			{
       
   882 			/* the following is for cases where spaces are
       
   883 			 * removed from lines.
       
   884 			 */
       
   885 			if (space)
       
   886 				{
       
   887 				w=x=y=z=0;
       
   888 				}
       
   889 			else
       
   890 				{
       
   891 				w= *(in++)-' ';
       
   892 				x= *(in++)-' ';
       
   893 				y= *(in++)-' ';
       
   894 				z= *(in++)-' ';
       
   895 				}
       
   896 			if ((w > 63) || (x > 63) || (y > 63) || (z > 63))
       
   897 				{
       
   898 				k=0;
       
   899 				if (w == blank) k=1;
       
   900 				if (x == blank) k=2;
       
   901 				if (y == blank) k=3;
       
   902 				if (z == blank) k=4;
       
   903 				space=1;
       
   904 				switch (k) {
       
   905 				case 1:	w=0; in--;
       
   906 				case 2: x=0; in--;
       
   907 				case 3: y=0; in--;
       
   908 				case 4: z=0; in--;
       
   909 					break;
       
   910 				case 0:
       
   911 					space=0;
       
   912 					fprintf(stderr,"bad uuencoded data values\n");
       
   913 					w=x=y=z=0;
       
   914 					return(-1);
       
   915 					break;
       
   916 					}
       
   917 				}
       
   918 			l=(w<<18)|(x<<12)|(y<< 6)|(z    );
       
   919 			l2ccc(l,out);
       
   920 			}
       
   921 		if (*(in++) != '\n')
       
   922 			{
       
   923 			fprintf(stderr,"missing nl in uuencoded line\n");
       
   924 			w=x=y=z=0;
       
   925 			return(-1);
       
   926 			}
       
   927 		j++;
       
   928 		}
       
   929 	*out='\0';
       
   930 	w=x=y=z=0;
       
   931 	return(n);
       
   932 	}