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#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 } 933