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