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