1 /* crypto/des/des.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 93 void usage(void); 94 void doencryption(void); 95 int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp); 96 void uufwriteEnd(FILE *fp); 97 int uufread(unsigned char *out,int size,unsigned int num,FILE *fp); 98 int uuencode(unsigned char *in,int num,unsigned char *out); 99 int uudecode(unsigned char *in,int num,unsigned char *out); 100 void 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 :-) */ 113 char key[KEYSIZB+1]; 114 int do_encrypt,longk=0; 115 FILE *DES_IN,*DES_OUT,*CKSUM_OUT; 116 char uuname[200]; 117 unsigned char uubuf[50]; 118 int uubufnum=0; 119 #define INUUBUFN (45*100) 120 #define OUTUUBUF (65*100) 121 unsigned char b[OUTUUBUF]; 122 unsigned char bb[300]; 123 DES_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 124 char cksumname[200]=""; 125 126 int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error; 127 128 int 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 322 void 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.", 349 NULL 350 }; 351 for (u=(char **)Usage; *u; u++) 352 { 353 fputs(*u,stderr); 354 fputc('\n',stderr); 355 } 356 357 EXIT(1); 358 } 359 360 void 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 } 668 problems: 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 */ 685 int 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 738 void 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 :-) */ 755 int 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 827 int 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 857 int 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 } 933