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