blob: 343135ff9ec505e2c0865706997a44bb249b17c7 [file] [log] [blame]
Kinson Chika8fa74c2011-07-29 11:33:41 -07001/* 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
93void usage(void);
94void doencryption(void);
95int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
96void uufwriteEnd(FILE *fp);
97int uufread(unsigned char *out,int size,unsigned int num,FILE *fp);
98int uuencode(unsigned char *in,int num,unsigned char *out);
99int uudecode(unsigned char *in,int num,unsigned char *out);
100void 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 :-) */
113char key[KEYSIZB+1];
114int do_encrypt,longk=0;
115FILE *DES_IN,*DES_OUT,*CKSUM_OUT;
116char uuname[200];
117unsigned char uubuf[50];
118int uubufnum=0;
119#define INUUBUFN (45*100)
120#define OUTUUBUF (65*100)
121unsigned char b[OUTUUBUF];
122unsigned char bb[300];
123DES_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
124char cksumname[200]="";
125
126int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error;
127
128int 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
322void 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.",
349NULL
350};
351 for (u=(char **)Usage; *u; u++)
352 {
353 fputs(*u,stderr);
354 fputc('\n',stderr);
355 }
356
357 EXIT(1);
358 }
359
360void 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 }
668problems:
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 */
685int 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
738void 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 :-) */
755int 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
827int 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
857int 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 }