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