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