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