1 /* 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 #ifndef MSDOS 63 #ifndef VMS 64 #include <openssl/opensslconf.h> 65 #include OPENSSL_UNISTD 66 #else /* VMS */ 67 #ifdef __DECC 68 #include <unistd.h> 69 #else /* not __DECC */ 70 #include <math.h> 71 #endif /* __DECC */ 72 #endif /* VMS */ 73 #else /* MSDOS */ 74 #include <io.h> 75 #endif 76 77 #include <time.h> 78 #include "des_ver.h" 79 80 #ifdef 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 92 void usage(void); 93 void doencryption(void); 94 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp); 95 void uufwriteEnd(FILE *fp); 96 int uufread(unsigned char *out,int size,unsigned int num,FILE *fp); 97 int uuencode(unsigned char *in,int num,unsigned char *out); 98 int uudecode(unsigned char *in,int num,unsigned char *out); 99 void 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); 102 #ifdef VMS 103 #define EXIT(a) exit(a&0x10000000L) 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 :-) */ 112 char key[KEYSIZB+1]; 113 int do_encrypt,longk=0; 114 FILE *DES_IN,*DES_OUT,*CKSUM_OUT; 115 char uuname[200]; 116 unsigned char uubuf[50]; 117 int uubufnum=0; 118 #define INUUBUFN (45*100) 119 #define OUTUUBUF (65*100) 120 unsigned char b[OUTUUBUF]; 121 unsigned char bb[300]; 122 des_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 123 char cksumname[200]=""; 124 125 int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error; 126 127 int main(int argc, char **argv) 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) && 261 #ifndef MSDOS 262 (stat(in,&ins) != -1) && 263 (stat(out,&outs) != -1) && 264 (ins.st_dev == outs.st_dev) && 265 (ins.st_ino == outs.st_ino)) 266 #else /* MSDOS */ 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 301 #ifdef MSDOS 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 318 void usage(void) 319 { 320 char **u; 321 static const char *Usage[]={ 322 "des <options> [input-file [output-file]]", 323 "options:", 324 "-v : des(1) version number", 325 "-e : encrypt using SunOS compatible user key to DES key conversion.", 326 "-E : encrypt ", 327 "-d : decrypt using SunOS compatible user key to DES key conversion.", 328 "-D : decrypt ", 329 "-c[ckname] : generate a cbc_cksum using SunOS compatible user key to", 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'", 336 "-h : the key that is entered will be a hexadecimal number", 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).", 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", 342 " generated from the input key. If the input key is less", 343 " than 8 characters long, this is equivalent to normal", 344 " encryption. Default is triple cbc, -b makes it triple ecb.", 345 NULL 346 }; 347 for (u=(char **)Usage; *u; u++) 348 { 349 fputs(*u,stderr); 350 fputc('\n',stderr); 351 } 352 353 EXIT(1); 354 } 355 356 void doencryption(void) 357 { 358 #ifdef _LIBC 359 extern unsigned long time(); 360 #endif 361 362 register int i; 363 des_key_schedule ks,ks2; 364 des_cblock iv,iv2; 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; 370 #ifndef MSDOS 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 { 377 if ( (( buf=OPENSSL_malloc(BUFSIZE+8)) == NULL) || 378 ((obuf=OPENSSL_malloc(BUFSIZE+8)) == NULL)) 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 } 425 des_set_key_unchecked(&k2,ks2); 426 memset(k2,0,sizeof(k2)); 427 } 428 else if (longk || flag3) 429 { 430 if (flag3) 431 { 432 des_string_to_2keys(key,&kk,&k2); 433 des_set_key_unchecked(&k2,ks2); 434 memset(k2,0,sizeof(k2)); 435 } 436 else 437 des_string_to_key(key,&kk); 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 455 des_set_key_unchecked(&kk,ks); 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 { 483 for (i=7-rem; i>0; i--) 484 RAND_pseudo_bytes(buf + l++, 1); 485 buf[l++]=rem; 486 ex=1; 487 len+=rem; 488 } 489 else 490 l-=rem; 491 492 if (cflag) 493 { 494 des_cbc_cksum(buf,&cksum, 495 (long)len,ks,&cksum); 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, 523 (long)l,ks,ks2,&iv, 524 &iv2,do_encrypt); 525 if (rem) memcpy(&(buf[l]),tmpbuf, 526 (unsigned int)rem); 527 } 528 else 529 { 530 des_cbc_encrypt( 531 buf,obuf, 532 (long)l,ks,&iv,do_encrypt); 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, 598 (long)l,ks,ks2,&iv, 599 &iv2,do_encrypt); 600 } 601 else 602 { 603 des_cbc_encrypt( 604 buf,obuf, 605 (long)l,ks,&iv,do_encrypt); 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; 630 if (cflag) des_cbc_cksum(obuf, 631 (des_cblock *)cksum,(long)l/8*8,ks, 632 (des_cblock *)cksum); 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 } 664 problems: 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 680 /* We ignore this parameter but it should be > ~50 I believe */ 681 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp) 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 734 void uufwriteEnd(FILE *fp) 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 750 /* int size: should always be > ~ 60; I actually ignore this parameter :-) */ 751 int uufread(unsigned char *out, int size, unsigned int num, FILE *fp) 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 823 int uuencode(unsigned char *in, int num, unsigned char *out) 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 853 int uudecode(unsigned char *in, int num, unsigned char *out) 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 } 929