OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
des.c
Go to the documentation of this file.
1 /* crypto/des/des.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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,
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];
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 
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 
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  {
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)
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)
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);
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  {
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)
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)
595  (DES_cblock *)&(buf[i]),
596  (DES_cblock *)&(obuf[i]),
597  &ks,&ks2,do_encrypt);
598  else if (flag3 && !bflag)
599  {
601  (DES_cblock *)buf,(DES_cblock *)obuf,
602  (long)l,ks,ks2,&iv,
603  &iv2,do_encrypt);
604  }
605  else
606  {
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';
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  }