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