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