]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/des/des.c
Import of old SSLeay release: SSLeay 0.8.1b
[thirdparty/openssl.git] / crypto / des / des.c
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
95 void usage(void);
96 void doencryption(void);
97 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
98 void uufwriteEnd(FILE *fp);
99 int uufread(unsigned char *out,int size,unsigned int num,FILE *fp);
100 int uuencode(unsigned char *in,int num,unsigned char *out);
101 int uudecode(unsigned char *in,int num,unsigned char *out);
102 #else
103 void usage();
104 void doencryption();
105 int uufwrite();
106 void uufwriteEnd();
107 int uufread();
108 int uuencode();
109 int 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 :-) */
122 char key[KEYSIZB+1];
123 int do_encrypt,longk=0;
124 FILE *DES_IN,*DES_OUT,*CKSUM_OUT;
125 char uuname[200];
126 unsigned char uubuf[50];
127 int uubufnum=0;
128 #define INUUBUFN (45*100)
129 #define OUTUUBUF (65*100)
130 unsigned char b[OUTUUBUF];
131 unsigned char bb[300];
132 des_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
133 char cksumname[200]="";
134
135 int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error;
136
137 int main(argc, argv)
138 int argc;
139 char **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
330 void 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.",
357 NULL
358 };
359 for (u=(char **)Usage; *u; u++)
360 {
361 fputs(*u,stderr);
362 fputc('\n',stderr);
363 }
364
365 EXIT(1);
366 }
367
368 void 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 }
679 problems:
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
695 int uufwrite(data, size, num, fp)
696 unsigned char *data;
697 int size;
698 unsigned int num;
699 FILE *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
756 void uufwriteEnd(fp)
757 FILE *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
773 int uufread(out, size, num, fp)
774 unsigned char *out;
775 int size; /* should always be > ~ 60; I actually ignore this parameter :-) */
776 unsigned int num;
777 FILE *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
849 int uuencode(in, num, out)
850 unsigned char *in;
851 int num;
852 unsigned 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
882 int uudecode(in, num, out)
883 unsigned char *in;
884 int num;
885 unsigned 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 }