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