1 /* $NetBSD: enc_des.c,v 1.15 2012/01/09 15:25:33 christos 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.15 2012/01/09 15:25:33 christos 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 const 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 size_t 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, (const 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 waiting for the key to 432 * show up. If so, go ahead an call it now that we have the key. 433 */ 434 if (fbp->need_start) { 435 fbp->need_start = 0; 436 fb64_start(fbp, DIR_ENCRYPT, server); 437 } 438 } 439 440 /* 441 * We only accept a keyid of 0. If we get a keyid of 442 * 0, then mark the state as SUCCESS. 443 */ 444 int 445 cfb64_keyid(dir, kp, lenp) 446 int dir, *lenp; 447 unsigned char *kp; 448 { 449 return(fb64_keyid(dir, kp, lenp, &fb[CFB])); 450 } 451 452 int 453 ofb64_keyid(dir, kp, lenp) 454 int dir, *lenp; 455 unsigned char *kp; 456 { 457 return(fb64_keyid(dir, kp, lenp, &fb[OFB])); 458 } 459 460 int 461 fb64_keyid(dir, kp, lenp, fbp) 462 int dir, *lenp; 463 unsigned char *kp; 464 struct fb *fbp; 465 { 466 register int state = fbp->state[dir-1]; 467 468 if (*lenp != 1 || (*kp != '\0')) { 469 *lenp = 0; 470 return(state); 471 } 472 473 if (state == FAILED) 474 state = IN_PROGRESS; 475 476 state &= ~NO_KEYID; 477 478 return(fbp->state[dir-1] = state); 479 } 480 481 void 482 fb64_printsub(const unsigned char *data, int cnt, unsigned char *buf, 483 int buflen, const unsigned char *type) 484 { 485 char lbuf[32]; 486 register int i; 487 char *cp; 488 489 buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 490 buflen -= 1; 491 492 switch(data[2]) { 493 case FB64_IV: 494 snprintf(lbuf, sizeof(lbuf), "%s_IV", type); 495 cp = lbuf; 496 goto common; 497 498 case FB64_IV_OK: 499 snprintf(lbuf, sizeof(lbuf), "%s_IV_OK", type); 500 cp = lbuf; 501 goto common; 502 503 case FB64_IV_BAD: 504 snprintf(lbuf, sizeof(lbuf), "%s_IV_BAD", type); 505 cp = lbuf; 506 goto common; 507 508 default: 509 snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[2]); 510 cp = lbuf; 511 common: 512 for (; (buflen > 0) && (*buf = *cp++); buf++) 513 buflen--; 514 for (i = 3; i < cnt; i++) { 515 snprintf(lbuf, sizeof(lbuf), " %d", data[i]); 516 for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) 517 buflen--; 518 } 519 break; 520 } 521 } 522 523 void 524 cfb64_printsub(data, cnt, buf, buflen) 525 unsigned char *data, *buf; 526 int cnt, buflen; 527 { 528 fb64_printsub(data, cnt, buf, buflen, "CFB64"); 529 } 530 531 void 532 ofb64_printsub(data, cnt, buf, buflen) 533 unsigned char *data, *buf; 534 int cnt, buflen; 535 { 536 fb64_printsub(data, cnt, buf, buflen, "OFB64"); 537 } 538 539 void 540 fb64_stream_iv(seed, stp) 541 Block seed; 542 register struct stinfo *stp; 543 { 544 545 memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); 546 memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); 547 548 des_key_sched(&stp->str_ikey, stp->str_sched); 549 550 stp->str_index = sizeof(Block); 551 } 552 553 void 554 fb64_stream_key(key, stp) 555 Block *key; 556 register struct stinfo *stp; 557 { 558 memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); 559 des_key_sched(key, stp->str_sched); 560 561 memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); 562 563 stp->str_index = sizeof(Block); 564 } 565 566 /* 567 * DES 64 bit Cipher Feedback 568 * 569 * key --->+-----+ 570 * +->| DES |--+ 571 * | +-----+ | 572 * | v 573 * INPUT --(--------->(+)+---> DATA 574 * | | 575 * +-------------+ 576 * 577 * 578 * Given: 579 * iV: Initial vector, 64 bits (8 bytes) long. 580 * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 581 * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 582 * 583 * V0 = DES(iV, key) 584 * On = Dn ^ Vn 585 * V(n+1) = DES(On, key) 586 */ 587 588 void 589 cfb64_encrypt(s, c) 590 register unsigned char *s; 591 int c; 592 { 593 register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; 594 register int idx; 595 596 idx = stp->str_index; 597 while (c-- > 0) { 598 if (idx == sizeof(Block)) { 599 Block b; 600 des_ecb_encrypt(&stp->str_output, &b, stp->str_sched, 1); 601 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 602 idx = 0; 603 } 604 605 /* On encryption, we store (feed ^ data) which is cypher */ 606 *s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s); 607 s++; 608 idx++; 609 } 610 stp->str_index = idx; 611 } 612 613 int 614 cfb64_decrypt(data) 615 int data; 616 { 617 register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 618 int idx; 619 620 if (data == -1) { 621 /* 622 * Back up one byte. It is assumed that we will 623 * never back up more than one byte. If we do, this 624 * may or may not work. 625 */ 626 if (stp->str_index) 627 --stp->str_index; 628 return(0); 629 } 630 631 idx = stp->str_index++; 632 if (idx == sizeof(Block)) { 633 Block b; 634 des_ecb_encrypt(&stp->str_output, &b, stp->str_sched, 1); 635 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 636 stp->str_index = 1; /* Next time will be 1 */ 637 idx = 0; /* But now use 0 */ 638 } 639 640 /* On decryption we store (data) which is cypher. */ 641 stp->str_output[idx] = data; 642 return(data ^ stp->str_feed[idx]); 643 } 644 645 /* 646 * DES 64 bit Output Feedback 647 * 648 * key --->+-----+ 649 * +->| DES |--+ 650 * | +-----+ | 651 * +-----------+ 652 * v 653 * INPUT -------->(+) ----> DATA 654 * 655 * Given: 656 * iV: Initial vector, 64 bits (8 bytes) long. 657 * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 658 * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 659 * 660 * V0 = DES(iV, key) 661 * V(n+1) = DES(Vn, key) 662 * On = Dn ^ Vn 663 */ 664 void 665 ofb64_encrypt(s, c) 666 register unsigned char *s; 667 int c; 668 { 669 register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; 670 register int idx; 671 672 idx = stp->str_index; 673 while (c-- > 0) { 674 if (idx == sizeof(Block)) { 675 Block b; 676 des_ecb_encrypt(&stp->str_feed, &b, stp->str_sched, 1); 677 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 678 idx = 0; 679 } 680 *s++ ^= stp->str_feed[idx]; 681 idx++; 682 } 683 stp->str_index = idx; 684 } 685 686 int 687 ofb64_decrypt(data) 688 int data; 689 { 690 register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 691 int idx; 692 693 if (data == -1) { 694 /* 695 * Back up one byte. It is assumed that we will 696 * never back up more than one byte. If we do, this 697 * may or may not work. 698 */ 699 if (stp->str_index) 700 --stp->str_index; 701 return(0); 702 } 703 704 idx = stp->str_index++; 705 if (idx == sizeof(Block)) { 706 Block b; 707 des_ecb_encrypt(&stp->str_feed, &b, stp->str_sched, 1); 708 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 709 stp->str_index = 1; /* Next time will be 1 */ 710 idx = 0; /* But now use 0 */ 711 } 712 713 return(data ^ stp->str_feed[idx]); 714 } 715 # endif /* DES_ENCRYPTION */ 716 # endif /* AUTHENTICATION */ 717 #endif /* ENCRYPTION */ 718