enc_des.c revision 84305
1/*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: head/contrib/telnet/libtelnet/enc_des.c 84305 2001-10-01 16:04:55Z markm $ 34 */ 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: head/contrib/telnet/libtelnet/enc_des.c 84305 2001-10-01 16:04:55Z markm $"); 38 39#ifndef lint 40static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; 41#endif /* not lint */ 42 43#ifdef ENCRYPTION 44# ifdef AUTHENTICATION 45# ifdef DES_ENCRYPTION 46#include <arpa/telnet.h> 47#include <stdio.h> 48#ifdef __STDC__ 49#include <stdlib.h> 50#endif 51 52#include <openssl/des.h> 53#include <string.h> 54#include "encrypt.h" 55#include "key-proto.h" 56#include "misc-proto.h" 57 58extern int encrypt_debug_mode; 59void des_set_random_generator_seed(des_cblock *); /* XXX */ 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 72struct 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 92static struct fb fb[2]; 93 94struct 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 121void fb64_stream_iv P((Block, struct stinfo *)); 122void fb64_init P((struct fb *)); 123static int fb64_start P((struct fb *, int, int)); 124int fb64_is P((unsigned char *, int, struct fb *)); 125int fb64_reply P((unsigned char *, int, struct fb *)); 126static void fb64_session P((Session_Key *, int, struct fb *)); 127void fb64_stream_key P((Block, struct stinfo *)); 128int fb64_keyid P((int, unsigned char *, int *, struct fb *)); 129 130 void 131cfb64_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 141ofb64_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 151fb64_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 171cfb64_start(dir, server) 172 int dir; 173 int server; 174{ 175 return(fb64_start(&fb[CFB], dir, server)); 176} 177 int 178ofb64_start(dir, server) 179 int dir; 180 int server; 181{ 182 return(fb64_start(&fb[OFB], dir, server)); 183} 184 185 static int 186fb64_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((Block *)fbp->temp_feed); 226 des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)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 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 254cfb64_is(data, cnt) 255 unsigned char *data; 256 int cnt; 257{ 258 return(fb64_is(data, cnt, &fb[CFB])); 259} 260 int 261ofb64_is(data, cnt) 262 unsigned char *data; 263 int cnt; 264{ 265 return(fb64_is(data, cnt, &fb[OFB])); 266} 267 268 int 269fb64_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 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 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 343cfb64_reply(data, cnt) 344 unsigned char *data; 345 int cnt; 346{ 347 return(fb64_reply(data, cnt, &fb[CFB])); 348} 349 int 350ofb64_reply(data, cnt) 351 unsigned char *data; 352 int cnt; 353{ 354 return(fb64_reply(data, cnt, &fb[OFB])); 355} 356 357 358 int 359fb64_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 399cfb64_session(key, server) 400 Session_Key *key; 401 int server; 402{ 403 fb64_session(key, server, &fb[CFB]); 404} 405 406 void 407ofb64_session(key, server) 408 Session_Key *key; 409 int server; 410{ 411 fb64_session(key, server, &fb[OFB]); 412} 413 414 static void 415fb64_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_set_random_generator_seed((Block *)fbp->krbdes_key); 434 fbp->once = 1; 435 } 436 des_key_sched((Block *)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 453cfb64_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 461ofb64_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 469fb64_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 490fb64_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 533cfb64_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 541ofb64_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 549fb64_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((Block *)stp->str_ikey, stp->str_sched); 558 559 stp->str_index = sizeof(Block); 560} 561 562 void 563fb64_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((Block *)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 598cfb64_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 index; 604 605 index = stp->str_index; 606 while (c-- > 0) { 607 if (index == sizeof(Block)) { 608 Block b; 609 des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 610 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 611 index = 0; 612 } 613 614 /* On encryption, we store (feed ^ data) which is cypher */ 615 *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); 616 s++; 617 index++; 618 } 619 stp->str_index = index; 620} 621 622 int 623cfb64_decrypt(data) 624 int data; 625{ 626 register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 627 int index; 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 index = stp->str_index++; 641 if (index == sizeof(Block)) { 642 Block b; 643 des_ecb_encrypt((Block *)stp->str_output, (Block *)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 index = 0; /* But now use 0 */ 647 } 648 649 /* On decryption we store (data) which is cypher. */ 650 stp->str_output[index] = data; 651 return(data ^ stp->str_feed[index]); 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 674ofb64_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 index; 680 681 index = stp->str_index; 682 while (c-- > 0) { 683 if (index == sizeof(Block)) { 684 Block b; 685 des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 686 memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 687 index = 0; 688 } 689 *s++ ^= stp->str_feed[index]; 690 index++; 691 } 692 stp->str_index = index; 693} 694 695 int 696ofb64_decrypt(data) 697 int data; 698{ 699 register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 700 int index; 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 index = stp->str_index++; 714 if (index == sizeof(Block)) { 715 Block b; 716 des_ecb_encrypt((Block *)stp->str_feed, (Block *)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 index = 0; /* But now use 0 */ 720 } 721 722 return(data ^ stp->str_feed[index]); 723} 724# endif /* DES_ENCRYPTION */ 725# endif /* AUTHENTICATION */ 726#endif /* ENCRYPTION */ 727