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