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