1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; 36 #endif /* not lint */ 37 38 #ifdef ENCRYPTION 39 # ifdef AUTHENTICATION 40 # ifdef DES_ENCRYPTION 41 #include <arpa/telnet.h> 42 #include <stdio.h> 43 #ifdef __STDC__ 44 #include <stdlib.h> 45 #endif 46 47 #include <des.h> 48 #include <string.h> 49 #include "encrypt.h" 50 #include "key-proto.h" 51 #include "misc-proto.h" 52 53 extern encrypt_debug_mode; 54 55 #define CFB 0 56 #define OFB 1 57 58 #define NO_SEND_IV 1 59 #define NO_RECV_IV 2 60 #define NO_KEYID 4 61 #define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) 62 #define SUCCESS 0 63 #define FAILED -1 64 65 66 struct fb { 67 Block krbdes_key; 68 Schedule krbdes_sched; 69 Block temp_feed; 70 unsigned char fb_feed[64]; 71 int need_start; 72 int state[2]; 73 int keyid[2]; 74 int once; 75 struct stinfo { 76 Block str_output; 77 Block str_feed; 78 Block str_iv; 79 Block str_ikey; 80 Schedule str_sched; 81 int str_index; 82 int str_flagshift; 83 } streams[2]; 84 }; 85 86 static struct fb fb[2]; 87 88 struct keyidlist { 89 char *keyid; 90 int keyidlen; 91 char *key; 92 int keylen; 93 int flags; 94 } keyidlist [] = { 95 { "\0", 1, 0, 0, 0 }, /* default key of zero */ 96 { 0, 0, 0, 0, 0 } 97 }; 98 99 #define KEYFLAG_MASK 03 100 101 #define KEYFLAG_NOINIT 00 102 #define KEYFLAG_INIT 01 103 #define KEYFLAG_OK 02 104 #define KEYFLAG_BAD 03 105 106 #define KEYFLAG_SHIFT 2 107 108 #define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) 109 110 #define FB64_IV 1 111 #define FB64_IV_OK 2 112 #define FB64_IV_BAD 3 113 114 115 void fb64_stream_iv P((Block, struct stinfo *)); 116 void fb64_init P((struct fb *)); 117 static int fb64_start P((struct fb *, int, int)); 118 int fb64_is P((unsigned char *, int, struct fb *)); 119 int fb64_reply P((unsigned char *, int, struct fb *)); 120 static void fb64_session P((Session_Key *, int, struct fb *)); 121 void fb64_stream_key P((Block, struct stinfo *)); 122 int fb64_keyid P((int, unsigned char *, int *, struct fb *)); 123 124 void 125 cfb64_init(server) 126 int server; 127 { 128 fb64_init(&fb[CFB]); 129 fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; 130 fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); 131 fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); 132 } 133 134 void 135 ofb64_init(server) 136 int server; 137 { 138 fb64_init(&fb[OFB]); 139 fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; 140 fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); 141 fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); 142 } 143 144 void 145 fb64_init(fbp) 146 register struct fb *fbp; 147 { 148 memset((void *)fbp, 0, sizeof(*fbp)); 149 fbp->state[0] = fbp->state[1] = FAILED; 150 fbp->fb_feed[0] = IAC; 151 fbp->fb_feed[1] = SB; 152 fbp->fb_feed[2] = TELOPT_ENCRYPT; 153 fbp->fb_feed[3] = ENCRYPT_IS; 154 } 155 156 /* 157 * Returns: 158 * -1: some error. Negotiation is done, encryption not ready. 159 * 0: Successful, initial negotiation all done. 160 * 1: successful, negotiation not done yet. 161 * 2: Not yet. Other things (like getting the key from 162 * Kerberos) have to happen before we can continue. 163 */ 164 int 165 cfb64_start(dir, server) 166 int dir; 167 int server; 168 { 169 return(fb64_start(&fb[CFB], dir, server)); 170 } 171 int 172 ofb64_start(dir, server) 173 int dir; 174 int server; 175 { 176 return(fb64_start(&fb[OFB], dir, server)); 177 } 178 179 static int 180 fb64_start(fbp, dir, server) 181 struct fb *fbp; 182 int dir; 183 int server; 184 { 185 int x; 186 unsigned char *p; 187 register int state; 188 189 switch (dir) { 190 case DIR_DECRYPT: 191 /* 192 * This is simply a request to have the other side 193 * start output (our input). He will negotiate an 194 * IV so we need not look for it. 195 */ 196 state = fbp->state[dir-1]; 197 if (state == FAILED) 198 state = IN_PROGRESS; 199 break; 200 201 case DIR_ENCRYPT: 202 state = fbp->state[dir-1]; 203 if (state == FAILED) 204 state = IN_PROGRESS; 205 else if ((state & NO_SEND_IV) == 0) 206 break; 207 208 if (!VALIDKEY(fbp->krbdes_key)) { 209 fbp->need_start = 1; 210 break; 211 } 212 state &= ~NO_SEND_IV; 213 state |= NO_RECV_IV; 214 if (encrypt_debug_mode) 215 printf("Creating new feed\r\n"); 216 /* 217 * Create a random feed and send it over. 218 */ 219 des_new_random_key((Block *)fbp->temp_feed); 220 des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, 221 fbp->krbdes_sched, 1); 222 p = fbp->fb_feed + 3; 223 *p++ = ENCRYPT_IS; 224 p++; 225 *p++ = FB64_IV; 226 for (x = 0; x < sizeof(Block); ++x) { 227 if ((*p++ = fbp->temp_feed[x]) == IAC) 228 *p++ = IAC; 229 } 230 *p++ = IAC; 231 *p++ = SE; 232 printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 233 net_write(fbp->fb_feed, p - fbp->fb_feed); 234 break; 235 default: 236 return(FAILED); 237 } 238 return(fbp->state[dir-1] = state); 239 } 240 241 /* 242 * Returns: 243 * -1: some error. Negotiation is done, encryption not ready. 244 * 0: Successful, initial negotiation all done. 245 * 1: successful, negotiation not done yet. 246 */ 247 int 248 cfb64_is(data, cnt) 249 unsigned char *data; 250 int cnt; 251 { 252 return(fb64_is(data, cnt, &fb[CFB])); 253 } 254 int 255 ofb64_is(data, cnt) 256 unsigned char *data; 257 int cnt; 258 { 259 return(fb64_is(data, cnt, &fb[OFB])); 260 } 261 262 int 263 fb64_is(data, cnt, fbp) 264 unsigned char *data; 265 int cnt; 266 struct fb *fbp; 267 { 268 unsigned char *p; 269 register int state = fbp->state[DIR_DECRYPT-1]; 270 271 if (cnt-- < 1) 272 goto failure; 273 274 switch (*data++) { 275 case FB64_IV: 276 if (cnt != sizeof(Block)) { 277 if (encrypt_debug_mode) 278 printf("CFB64: initial vector failed on size\r\n"); 279 state = FAILED; 280 goto failure; 281 } 282 283 if (encrypt_debug_mode) 284 printf("CFB64: initial vector received\r\n"); 285 286 if (encrypt_debug_mode) 287 printf("Initializing Decrypt stream\r\n"); 288 289 fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); 290 291 p = fbp->fb_feed + 3; 292 *p++ = ENCRYPT_REPLY; 293 p++; 294 *p++ = FB64_IV_OK; 295 *p++ = IAC; 296 *p++ = SE; 297 printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 298 net_write(fbp->fb_feed, p - fbp->fb_feed); 299 300 state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; 301 break; 302 303 default: 304 if (encrypt_debug_mode) { 305 printf("Unknown option type: %d\r\n", *(data-1)); 306 printd(data, cnt); 307 printf("\r\n"); 308 } 309 /* FALL THROUGH */ 310 failure: 311 /* 312 * We failed. Send an FB64_IV_BAD option 313 * to the other side so it will know that 314 * things failed. 315 */ 316 p = fbp->fb_feed + 3; 317 *p++ = ENCRYPT_REPLY; 318 p++; 319 *p++ = FB64_IV_BAD; 320 *p++ = IAC; 321 *p++ = SE; 322 printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 323 net_write(fbp->fb_feed, p - fbp->fb_feed); 324 325 break; 326 } 327 return(fbp->state[DIR_DECRYPT-1] = state); 328 } 329 330 /* 331 * Returns: 332 * -1: some error. Negotiation is done, encryption not ready. 333 * 0: Successful, initial negotiation all done. 334 * 1: successful, negotiation not done yet. 335 */ 336 int 337 cfb64_reply(data, cnt) 338 unsigned char *data; 339 int cnt; 340 { 341 return(fb64_reply(data, cnt, &fb[CFB])); 342 } 343 int 344 ofb64_reply(data, cnt) 345 unsigned char *data; 346 int cnt; 347 { 348 return(fb64_reply(data, cnt, &fb[OFB])); 349 } 350 351 352 int 353 fb64_reply(data, cnt, fbp) 354 unsigned char *data; 355 int cnt; 356 struct fb *fbp; 357 { 358 register int state = fbp->state[DIR_ENCRYPT-1]; 359 360 if (cnt-- < 1) 361 goto failure; 362 363 switch (*data++) { 364 case FB64_IV_OK: 365 fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 366 if (state == FAILED) 367 state = IN_PROGRESS; 368 state &= ~NO_RECV_IV; 369 encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); 370 break; 371 372 case FB64_IV_BAD: 373 memset(fbp->temp_feed, 0, sizeof(Block)); 374 fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 375 state = FAILED; 376 break; 377 378 default: 379 if (encrypt_debug_mode) { 380 printf("Unknown option type: %d\r\n", data[-1]); 381 printd(data, cnt); 382 printf("\r\n"); 383 } 384 /* FALL THROUGH */ 385 failure: 386 state = FAILED; 387 break; 388 } 389 return(fbp->state[DIR_ENCRYPT-1] = state); 390 } 391 392 void 393 cfb64_session(key, server) 394 Session_Key *key; 395 int server; 396 { 397 fb64_session(key, server, &fb[CFB]); 398 } 399 400 void 401 ofb64_session(key, server) 402 Session_Key *key; 403 int server; 404 { 405 fb64_session(key, server, &fb[OFB]); 406 } 407 408 static void 409 fb64_session(key, server, fbp) 410 Session_Key *key; 411 int server; 412 struct fb *fbp; 413 { 414 415 if (!key || key->type != SK_DES) { 416 if (encrypt_debug_mode) 417 printf("Can't set krbdes's session key (%d != %d)\r\n", 418 key ? key->type : -1, SK_DES); 419 return; 420 } 421 memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); 422 423 fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); 424 fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); 425 426 if (fbp->once == 0) { 427 des_set_random_generator_seed((Block *)fbp->krbdes_key); 428 fbp->once = 1; 429 } 430 des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); 431 /* 432 * Now look to see if krbdes_start() was was waiting for 433 * the key to show up. If so, go ahead an call it now 434 * that we have the key. 435 */ 436 if (fbp->need_start) { 437 fbp->need_start = 0; 438 fb64_start(fbp, DIR_ENCRYPT, server); 439 } 440 } 441 442 /* 443 * We only accept a keyid of 0. If we get a keyid of 444 * 0, then mark the state as SUCCESS. 445 */ 446 int 447 cfb64_keyid(dir, kp, lenp) 448 int dir, *lenp; 449 unsigned char *kp; 450 { 451 return(fb64_keyid(dir, kp, lenp, &fb[CFB])); 452 } 453 454 int 455 ofb64_keyid(dir, kp, lenp) 456 int dir, *lenp; 457 unsigned char *kp; 458 { 459 return(fb64_keyid(dir, kp, lenp, &fb[OFB])); 460 } 461 462 int 463 fb64_keyid(dir, kp, lenp, fbp) 464 int dir, *lenp; 465 unsigned char *kp; 466 struct fb *fbp; 467 { 468 register int state = fbp->state[dir-1]; 469 470 if (*lenp != 1 || (*kp != '\0')) { 471 *lenp = 0; 472 return(state); 473 } 474 475 if (state == FAILED) 476 state = IN_PROGRESS; 477 478 state &= ~NO_KEYID; 479 480 return(fbp->state[dir-1] = state); 481 } 482 483 void 484 fb64_printsub(data, cnt, buf, buflen, type) 485 unsigned char *data, *buf, *type; 486 int cnt, buflen; 487 { 488 char lbuf[32]; 489 register int i; 490 char *cp; 491 492 buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 493 buflen -= 1; 494 495 switch(data[2]) { 496 case FB64_IV: 497 sprintf(lbuf, "%s_IV", type); 498 cp = lbuf; 499 goto common; 500 501 case FB64_IV_OK: 502 sprintf(lbuf, "%s_IV_OK", type); 503 cp = lbuf; 504 goto common; 505 506 case FB64_IV_BAD: 507 sprintf(lbuf, "%s_IV_BAD", type); 508 cp = lbuf; 509 goto common; 510 511 default: 512 sprintf(lbuf, " %d (unknown)", data[2]); 513 cp = lbuf; 514 common: 515 for (; (buflen > 0) && (*buf = *cp++); buf++) 516 buflen--; 517 for (i = 3; i < cnt; i++) { 518 sprintf(lbuf, " %d", data[i]); 519 for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) 520 buflen--; 521 } 522 break; 523 } 524 } 525 526 void 527 cfb64_printsub(data, cnt, buf, buflen) 528 unsigned char *data, *buf; 529 int cnt, buflen; 530 { 531 fb64_printsub(data, cnt, buf, buflen, "CFB64"); 532 } 533 534 void 535 ofb64_printsub(data, cnt, buf, buflen) 536 unsigned char *data, *buf; 537 int cnt, buflen; 538 { 539 fb64_printsub(data, cnt, buf, buflen, "OFB64"); 540 } 541 542 void 543 fb64_stream_iv(seed, stp) 544 Block seed; 545 register struct stinfo *stp; 546 { 547 548 memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); 549 memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); 550 551 des_key_sched((Block *)stp->str_ikey, stp->str_sched); 552 553 stp->str_index = sizeof(Block); 554 } 555 556 void 557 fb64_stream_key(key, stp) 558 Block key; 559 register struct stinfo *stp; 560 { 561 memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); 562 des_key_sched((Block *)key, stp->str_sched); 563 564 memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); 565 566 stp->str_index = sizeof(Block); 567 } 568 569 /* 570 * DES 64 bit Cipher Feedback 571 * 572 * key --->+-----+ 573 * +->| DES |--+ 574 * | +-----+ | 575 * | v 576 * INPUT --(--------->(+)+---> DATA 577 * | | 578 * +-------------+ 579 * 580 * 581 * Given: 582 * iV: Initial vector, 64 bits (8 bytes) long. 583 * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 584 * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 585 * 586 * V0 = DES(iV, key) 587 * On = Dn ^ Vn 588 * V(n+1) = DES(On, key) 589 */ 590 591 void 592 cfb64_encrypt(s, c) 593 register unsigned char *s; 594 int c; 595 { 596 register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; 597 register int index; 598 599 index = stp->str_index; 600 while (c-- > 0) { 601 if (index == sizeof(Block)) { 602 Block b; 603 des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 604 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 605 index = 0; 606 } 607 608 /* On encryption, we store (feed ^ data) which is cypher */ 609 *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); 610 s++; 611 index++; 612 } 613 stp->str_index = index; 614 } 615 616 int 617 cfb64_decrypt(data) 618 int data; 619 { 620 register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 621 int index; 622 623 if (data == -1) { 624 /* 625 * Back up one byte. It is assumed that we will 626 * never back up more than one byte. If we do, this 627 * may or may not work. 628 */ 629 if (stp->str_index) 630 --stp->str_index; 631 return(0); 632 } 633 634 index = stp->str_index++; 635 if (index == sizeof(Block)) { 636 Block b; 637 des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 638 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 639 stp->str_index = 1; /* Next time will be 1 */ 640 index = 0; /* But now use 0 */ 641 } 642 643 /* On decryption we store (data) which is cypher. */ 644 stp->str_output[index] = data; 645 return(data ^ stp->str_feed[index]); 646 } 647 648 /* 649 * DES 64 bit Output Feedback 650 * 651 * key --->+-----+ 652 * +->| DES |--+ 653 * | +-----+ | 654 * +-----------+ 655 * v 656 * INPUT -------->(+) ----> DATA 657 * 658 * Given: 659 * iV: Initial vector, 64 bits (8 bytes) long. 660 * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 661 * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 662 * 663 * V0 = DES(iV, key) 664 * V(n+1) = DES(Vn, key) 665 * On = Dn ^ Vn 666 */ 667 void 668 ofb64_encrypt(s, c) 669 register unsigned char *s; 670 int c; 671 { 672 register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; 673 register int index; 674 675 index = stp->str_index; 676 while (c-- > 0) { 677 if (index == sizeof(Block)) { 678 Block b; 679 des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 680 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 681 index = 0; 682 } 683 *s++ ^= stp->str_feed[index]; 684 index++; 685 } 686 stp->str_index = index; 687 } 688 689 int 690 ofb64_decrypt(data) 691 int data; 692 { 693 register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 694 int index; 695 696 if (data == -1) { 697 /* 698 * Back up one byte. It is assumed that we will 699 * never back up more than one byte. If we do, this 700 * may or may not work. 701 */ 702 if (stp->str_index) 703 --stp->str_index; 704 return(0); 705 } 706 707 index = stp->str_index++; 708 if (index == sizeof(Block)) { 709 Block b; 710 des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 711 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 712 stp->str_index = 1; /* Next time will be 1 */ 713 index = 0; /* But now use 0 */ 714 } 715 716 return(data ^ stp->str_feed[index]); 717 } 718 # endif /* DES_ENCRYPTION */ 719 # endif /* AUTHENTICATION */ 720 #endif /* ENCRYPTION */ 721