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