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