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