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