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