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