encrypt.c revision 29181
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  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
35static const char sccsid[] = "@(#)encrypt.c	8.2 (Berkeley) 5/30/95";
36#endif /* not lint */
37
38/*
39 * Copyright (C) 1990 by the Massachusetts Institute of Technology
40 *
41 * Export of this software from the United States of America is assumed
42 * to require a specific license from the United States Government.
43 * It is the responsibility of any person or organization contemplating
44 * export to obtain such a license before exporting.
45 *
46 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
47 * distribute this software and its documentation for any purpose and
48 * without fee is hereby granted, provided that the above copyright
49 * notice appear in all copies and that both that copyright notice and
50 * this permission notice appear in supporting documentation, and that
51 * the name of M.I.T. not be used in advertising or publicity pertaining
52 * to distribution of the software without specific, written prior
53 * permission.  M.I.T. makes no representations about the suitability of
54 * this software for any purpose.  It is provided "as is" without express
55 * or implied warranty.
56 */
57
58#ifdef	ENCRYPTION
59
60#define	ENCRYPT_NAMES
61#include <stdio.h>
62#include <arpa/telnet.h>
63
64#include "encrypt.h"
65#include "misc.h"
66
67#ifdef	__STDC__
68#include <stdlib.h>
69#endif
70#ifdef	NO_STRING_H
71#include <strings.h>
72#else
73#include <string.h>
74#endif
75
76/*
77 * These functions pointers point to the current routines
78 * for encrypting and decrypting data.
79 */
80void	(*encrypt_output) P((unsigned char *, int));
81int	(*decrypt_input) P((int));
82
83int EncryptType(char *type, char *mode);
84int EncryptStart(char *mode);
85int EncryptStop(char *mode);
86int EncryptStartInput(void);
87int EncryptStartOutput(void);
88int EncryptStopInput(void);
89int EncryptStopOutput(void);
90
91int Ambiguous(char **s);
92int isprefix(char *s1, char *s2);
93char **genget(char *name, char **table, int stlen);
94
95int encrypt_debug_mode = 0;
96static int decrypt_mode = 0;
97static int encrypt_mode = 0;
98static int encrypt_verbose = 0;
99static int autoencrypt = 0;
100static int autodecrypt = 0;
101static int havesessionkey = 0;
102static int Server = 0;
103static char *Name = "Noname";
104
105#define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
106
107static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64)
108				| typemask(ENCTYPE_DES_OFB64);
109static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64)
110				| typemask(ENCTYPE_DES_OFB64);
111static long i_wont_support_encrypt = 0;
112static long i_wont_support_decrypt = 0;
113#define	I_SUPPORT_ENCRYPT	(i_support_encrypt & ~i_wont_support_encrypt)
114#define	I_SUPPORT_DECRYPT	(i_support_decrypt & ~i_wont_support_decrypt)
115
116static long remote_supports_encrypt = 0;
117static long remote_supports_decrypt = 0;
118
119static Encryptions encryptions[] = {
120#ifdef	DES_ENCRYPTION
121    { "DES_CFB64",	ENCTYPE_DES_CFB64,
122			cfb64_encrypt,
123			cfb64_decrypt,
124			cfb64_init,
125			cfb64_start,
126			cfb64_is,
127			cfb64_reply,
128			cfb64_session,
129			cfb64_keyid,
130			cfb64_printsub },
131    { "DES_OFB64",	ENCTYPE_DES_OFB64,
132			ofb64_encrypt,
133			ofb64_decrypt,
134			ofb64_init,
135			ofb64_start,
136			ofb64_is,
137			ofb64_reply,
138			ofb64_session,
139			ofb64_keyid,
140			ofb64_printsub },
141#endif	/* DES_ENCRYPTION */
142    { 0, },
143};
144
145static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
146					 ENCRYPT_SUPPORT };
147static unsigned char str_suplen = 0;
148static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
149static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
150
151	Encryptions *
152findencryption(type)
153	int type;
154{
155	Encryptions *ep = encryptions;
156
157	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
158		return(0);
159	while (ep->type && ep->type != type)
160		++ep;
161	return(ep->type ? ep : 0);
162}
163
164	Encryptions *
165finddecryption(type)
166	int type;
167{
168	Encryptions *ep = encryptions;
169
170	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
171		return(0);
172	while (ep->type && ep->type != type)
173		++ep;
174	return(ep->type ? ep : 0);
175}
176
177#define	MAXKEYLEN 64
178
179static struct key_info {
180	unsigned char keyid[MAXKEYLEN];
181	int keylen;
182	int dir;
183	int *modep;
184	Encryptions *(*getcrypt)();
185} ki[2] = {
186	{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
187	{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
188};
189
190static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len);
191
192	void
193encrypt_init(name, server)
194	char *name;
195	int server;
196{
197	Encryptions *ep = encryptions;
198
199	Name = name;
200	Server = server;
201	i_support_encrypt = i_support_decrypt = 0;
202	remote_supports_encrypt = remote_supports_decrypt = 0;
203	encrypt_mode = 0;
204	decrypt_mode = 0;
205	encrypt_output = 0;
206	decrypt_input = 0;
207#ifdef notdef
208	encrypt_verbose = !server;
209#endif
210
211	str_suplen = 4;
212
213	while (ep->type) {
214		if (encrypt_debug_mode)
215			printf(">>>%s: I will support %s\r\n",
216				Name, ENCTYPE_NAME(ep->type));
217		i_support_encrypt |= typemask(ep->type);
218		i_support_decrypt |= typemask(ep->type);
219		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
220			if ((str_send[str_suplen++] = ep->type) == IAC)
221				str_send[str_suplen++] = IAC;
222		if (ep->init)
223			(*ep->init)(Server);
224		++ep;
225	}
226	str_send[str_suplen++] = IAC;
227	str_send[str_suplen++] = SE;
228}
229
230	void
231encrypt_list_types()
232{
233	Encryptions *ep = encryptions;
234
235	printf("Valid encryption types:\n");
236	while (ep->type) {
237		printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
238		++ep;
239	}
240}
241
242	int
243EncryptEnable(type, mode)
244	char *type, *mode;
245{
246	if (isprefix(type, "help") || isprefix(type, "?")) {
247		printf("Usage: encrypt enable <type> [input|output]\n");
248		encrypt_list_types();
249		return(0);
250	}
251	if (EncryptType(type, mode))
252		return(EncryptStart(mode));
253	return(0);
254}
255
256	int
257EncryptDisable(type, mode)
258	char *type, *mode;
259{
260	register Encryptions *ep;
261	int ret = 0;
262
263	if (isprefix(type, "help") || isprefix(type, "?")) {
264		printf("Usage: encrypt disable <type> [input|output]\n");
265		encrypt_list_types();
266	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
267						sizeof(Encryptions))) == 0) {
268		printf("%s: invalid encryption type\n", type);
269	} else if (Ambiguous((char **)ep)) {
270		printf("Ambiguous type '%s'\n", type);
271	} else {
272		if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
273			if (decrypt_mode == ep->type)
274				EncryptStopInput();
275			i_wont_support_decrypt |= typemask(ep->type);
276			ret = 1;
277		}
278		if ((mode == 0) || (isprefix(mode, "output"))) {
279			if (encrypt_mode == ep->type)
280				EncryptStopOutput();
281			i_wont_support_encrypt |= typemask(ep->type);
282			ret = 1;
283		}
284		if (ret == 0)
285			printf("%s: invalid encryption mode\n", mode);
286	}
287	return(ret);
288}
289
290	int
291EncryptType(type, mode)
292	char *type;
293	char *mode;
294{
295	register Encryptions *ep;
296	int ret = 0;
297
298	if (isprefix(type, "help") || isprefix(type, "?")) {
299		printf("Usage: encrypt type <type> [input|output]\n");
300		encrypt_list_types();
301	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
302						sizeof(Encryptions))) == 0) {
303		printf("%s: invalid encryption type\n", type);
304	} else if (Ambiguous((char **)ep)) {
305		printf("Ambiguous type '%s'\n", type);
306	} else {
307		if ((mode == 0) || isprefix(mode, "input")) {
308			decrypt_mode = ep->type;
309			i_wont_support_decrypt &= ~typemask(ep->type);
310			ret = 1;
311		}
312		if ((mode == 0) || isprefix(mode, "output")) {
313			encrypt_mode = ep->type;
314			i_wont_support_encrypt &= ~typemask(ep->type);
315			ret = 1;
316		}
317		if (ret == 0)
318			printf("%s: invalid encryption mode\n", mode);
319	}
320	return(ret);
321}
322
323	int
324EncryptStart(mode)
325	char *mode;
326{
327	register int ret = 0;
328	if (mode) {
329		if (isprefix(mode, "input"))
330			return(EncryptStartInput());
331		if (isprefix(mode, "output"))
332			return(EncryptStartOutput());
333		if (isprefix(mode, "help") || isprefix(mode, "?")) {
334			printf("Usage: encrypt start [input|output]\n");
335			return(0);
336		}
337		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
338		return(0);
339	}
340	ret += EncryptStartInput();
341	ret += EncryptStartOutput();
342	return(ret);
343}
344
345	int
346EncryptStartInput()
347{
348	if (decrypt_mode) {
349		encrypt_send_request_start();
350		return(1);
351	}
352	printf("No previous decryption mode, decryption not enabled\r\n");
353	return(0);
354}
355
356	int
357EncryptStartOutput()
358{
359	if (encrypt_mode) {
360		encrypt_start_output(encrypt_mode);
361		return(1);
362	}
363	printf("No previous encryption mode, encryption not enabled\r\n");
364	return(0);
365}
366
367	int
368EncryptStop(mode)
369	char *mode;
370{
371	int ret = 0;
372	if (mode) {
373		if (isprefix(mode, "input"))
374			return(EncryptStopInput());
375		if (isprefix(mode, "output"))
376			return(EncryptStopOutput());
377		if (isprefix(mode, "help") || isprefix(mode, "?")) {
378			printf("Usage: encrypt stop [input|output]\n");
379			return(0);
380		}
381		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
382		return(0);
383	}
384	ret += EncryptStopInput();
385	ret += EncryptStopOutput();
386	return(ret);
387}
388
389	int
390EncryptStopInput()
391{
392	encrypt_send_request_end();
393	return(1);
394}
395
396	int
397EncryptStopOutput()
398{
399	encrypt_send_end();
400	return(1);
401}
402
403	void
404encrypt_display()
405{
406	if (encrypt_output)
407		printf("Currently encrypting output with %s\r\n",
408			ENCTYPE_NAME(encrypt_mode));
409	if (decrypt_input)
410		printf("Currently decrypting input with %s\r\n",
411			ENCTYPE_NAME(decrypt_mode));
412}
413
414	int
415EncryptStatus()
416{
417	if (encrypt_output)
418		printf("Currently encrypting output with %s\r\n",
419			ENCTYPE_NAME(encrypt_mode));
420	else if (encrypt_mode) {
421		printf("Currently output is clear text.\r\n");
422		printf("Last encryption mode was %s\r\n",
423			ENCTYPE_NAME(encrypt_mode));
424	}
425	if (decrypt_input) {
426		printf("Currently decrypting input with %s\r\n",
427			ENCTYPE_NAME(decrypt_mode));
428	} else if (decrypt_mode) {
429		printf("Currently input is clear text.\r\n");
430		printf("Last decryption mode was %s\r\n",
431			ENCTYPE_NAME(decrypt_mode));
432	}
433	return 1;
434}
435
436	void
437encrypt_send_support()
438{
439	if (str_suplen) {
440		/*
441		 * If the user has requested that decryption start
442		 * immediatly, then send a "REQUEST START" before
443		 * we negotiate the type.
444		 */
445		if (!Server && autodecrypt)
446			encrypt_send_request_start();
447		net_write(str_send, str_suplen);
448		printsub('>', &str_send[2], str_suplen - 2);
449		str_suplen = 0;
450	}
451}
452
453	int
454EncryptDebug(on)
455	int on;
456{
457	if (on < 0)
458		encrypt_debug_mode ^= 1;
459	else
460		encrypt_debug_mode = on;
461	printf("Encryption debugging %s\r\n",
462		encrypt_debug_mode ? "enabled" : "disabled");
463	return(1);
464}
465
466	int
467EncryptVerbose(on)
468	int on;
469{
470	if (on < 0)
471		encrypt_verbose ^= 1;
472	else
473		encrypt_verbose = on;
474	printf("Encryption %s verbose\r\n",
475		encrypt_verbose ? "is" : "is not");
476	return(1);
477}
478
479	int
480EncryptAutoEnc(on)
481	int on;
482{
483	encrypt_auto(on);
484	printf("Automatic encryption of output is %s\r\n",
485		autoencrypt ? "enabled" : "disabled");
486	return(1);
487}
488
489	int
490EncryptAutoDec(on)
491	int on;
492{
493	decrypt_auto(on);
494	printf("Automatic decryption of input is %s\r\n",
495		autodecrypt ? "enabled" : "disabled");
496	return(1);
497}
498
499/*
500 * Called when ENCRYPT SUPPORT is received.
501 */
502	void
503encrypt_support(typelist, cnt)
504	unsigned char *typelist;
505	int cnt;
506{
507	register int type, use_type = 0;
508	Encryptions *ep;
509
510	/*
511	 * Forget anything the other side has previously told us.
512	 */
513	remote_supports_decrypt = 0;
514
515	while (cnt-- > 0) {
516		type = *typelist++;
517		if (encrypt_debug_mode)
518			printf(">>>%s: He is supporting %s (%d)\r\n",
519				Name,
520				ENCTYPE_NAME(type), type);
521		if ((type < ENCTYPE_CNT) &&
522		    (I_SUPPORT_ENCRYPT & typemask(type))) {
523			remote_supports_decrypt |= typemask(type);
524			if (use_type == 0)
525				use_type = type;
526		}
527	}
528	if (use_type) {
529		ep = findencryption(use_type);
530		if (!ep)
531			return;
532		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
533		if (encrypt_debug_mode)
534			printf(">>>%s: (*ep->start)() returned %d\r\n",
535					Name, type);
536		if (type < 0)
537			return;
538		encrypt_mode = use_type;
539		if (type == 0)
540			encrypt_start_output(use_type);
541	}
542}
543
544	void
545encrypt_is(data, cnt)
546	unsigned char *data;
547	int cnt;
548{
549	Encryptions *ep;
550	register int type, ret;
551
552	if (--cnt < 0)
553		return;
554	type = *data++;
555	if (type < ENCTYPE_CNT)
556		remote_supports_encrypt |= typemask(type);
557	if (!(ep = finddecryption(type))) {
558		if (encrypt_debug_mode)
559			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
560				Name,
561				ENCTYPE_NAME_OK(type)
562					? ENCTYPE_NAME(type) : "(unknown)",
563				type);
564		return;
565	}
566	if (!ep->is) {
567		if (encrypt_debug_mode)
568			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
569				Name,
570				ENCTYPE_NAME_OK(type)
571					? ENCTYPE_NAME(type) : "(unknown)",
572				type);
573		ret = 0;
574	} else {
575		ret = (*ep->is)(data, cnt);
576		if (encrypt_debug_mode)
577			printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
578				(ret < 0) ? "FAIL " :
579				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
580	}
581	if (ret < 0) {
582		autodecrypt = 0;
583	} else {
584		decrypt_mode = type;
585		if (ret == 0 && autodecrypt)
586			encrypt_send_request_start();
587	}
588}
589
590	void
591encrypt_reply(data, cnt)
592	unsigned char *data;
593	int cnt;
594{
595	Encryptions *ep;
596	register int ret, type;
597
598	if (--cnt < 0)
599		return;
600	type = *data++;
601	if (!(ep = findencryption(type))) {
602		if (encrypt_debug_mode)
603			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
604				Name,
605				ENCTYPE_NAME_OK(type)
606					? ENCTYPE_NAME(type) : "(unknown)",
607				type);
608		return;
609	}
610	if (!ep->reply) {
611		if (encrypt_debug_mode)
612			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
613				Name,
614				ENCTYPE_NAME_OK(type)
615					? ENCTYPE_NAME(type) : "(unknown)",
616				type);
617		ret = 0;
618	} else {
619		ret = (*ep->reply)(data, cnt);
620		if (encrypt_debug_mode)
621			printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
622				data, cnt,
623				(ret < 0) ? "FAIL " :
624				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
625	}
626	if (encrypt_debug_mode)
627		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
628	if (ret < 0) {
629		autoencrypt = 0;
630	} else {
631		encrypt_mode = type;
632		if (ret == 0 && autoencrypt)
633			encrypt_start_output(type);
634	}
635}
636
637/*
638 * Called when a ENCRYPT START command is received.
639 */
640	void
641encrypt_start(data, cnt)
642	unsigned char *data;
643	int cnt;
644{
645	Encryptions *ep;
646
647	if (!decrypt_mode) {
648		/*
649		 * Something is wrong.  We should not get a START
650		 * command without having already picked our
651		 * decryption scheme.  Send a REQUEST-END to
652		 * attempt to clear the channel...
653		 */
654		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
655		encrypt_send_request_end();
656		return;
657	}
658
659	if ((ep = finddecryption(decrypt_mode))) {
660		decrypt_input = ep->input;
661		if (encrypt_verbose)
662			printf("[ Input is now decrypted with type %s ]\r\n",
663				ENCTYPE_NAME(decrypt_mode));
664		if (encrypt_debug_mode)
665			printf(">>>%s: Start to decrypt input with type %s\r\n",
666				Name, ENCTYPE_NAME(decrypt_mode));
667	} else {
668		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
669				Name,
670				ENCTYPE_NAME_OK(decrypt_mode)
671					? ENCTYPE_NAME(decrypt_mode)
672					: "(unknown)",
673				decrypt_mode);
674		encrypt_send_request_end();
675	}
676}
677
678	void
679encrypt_session_key(key, server)
680	Session_Key *key;
681	int server;
682{
683	Encryptions *ep = encryptions;
684
685	havesessionkey = 1;
686
687	while (ep->type) {
688		if (ep->session)
689			(*ep->session)(key, server);
690#ifdef notdef
691		if (!encrypt_output && autoencrypt && !server)
692			encrypt_start_output(ep->type);
693		if (!decrypt_input && autodecrypt && !server)
694			encrypt_send_request_start();
695#endif
696		++ep;
697	}
698}
699
700/*
701 * Called when ENCRYPT END is received.
702 */
703	void
704encrypt_end()
705{
706	decrypt_input = 0;
707	if (encrypt_debug_mode)
708		printf(">>>%s: Input is back to clear text\r\n", Name);
709	if (encrypt_verbose)
710		printf("[ Input is now clear text ]\r\n");
711}
712
713/*
714 * Called when ENCRYPT REQUEST-END is received.
715 */
716	void
717encrypt_request_end()
718{
719	encrypt_send_end();
720}
721
722/*
723 * Called when ENCRYPT REQUEST-START is received.  If we receive
724 * this before a type is picked, then that indicates that the
725 * other side wants us to start encrypting data as soon as we
726 * can.
727 */
728	void
729encrypt_request_start(data, cnt)
730	unsigned char *data;
731	int cnt;
732{
733	if (encrypt_mode == 0)  {
734		if (Server)
735			autoencrypt = 1;
736		return;
737	}
738	encrypt_start_output(encrypt_mode);
739}
740
741static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
742
743	void
744encrypt_enc_keyid(keyid, len)
745	unsigned char *keyid;
746	int len;
747{
748	encrypt_keyid(&ki[1], keyid, len);
749}
750
751	void
752encrypt_dec_keyid(keyid, len)
753	unsigned char *keyid;
754	int len;
755{
756	encrypt_keyid(&ki[0], keyid, len);
757}
758
759	void
760encrypt_keyid(kp, keyid, len)
761	struct key_info *kp;
762	unsigned char *keyid;
763	int len;
764{
765	Encryptions *ep;
766	int dir = kp->dir;
767	register int ret = 0;
768
769	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
770		if (len == 0)
771			return;
772		kp->keylen = 0;
773	} else if (len == 0) {
774		/*
775		 * Empty option, indicates a failure.
776		 */
777		if (kp->keylen == 0)
778			return;
779		kp->keylen = 0;
780		if (ep->keyid)
781			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
782
783	} else if ((len != kp->keylen) ||
784		   (memcmp(keyid, kp->keyid, len) != 0)) {
785		/*
786		 * Length or contents are different
787		 */
788		kp->keylen = len;
789		memmove(kp->keyid, keyid, len);
790		if (ep->keyid)
791			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
792	} else {
793		if (ep->keyid)
794			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
795		if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
796			encrypt_start_output(*kp->modep);
797		return;
798	}
799
800	encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
801}
802
803	void
804encrypt_send_keyid(dir, keyid, keylen, saveit)
805	int dir;
806	unsigned char *keyid;
807	int keylen;
808	int saveit;
809{
810	unsigned char *strp;
811
812	str_keyid[3] = (dir == DIR_ENCRYPT)
813			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
814	if (saveit) {
815		struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
816		memmove(kp->keyid, keyid, keylen);
817		kp->keylen = keylen;
818	}
819
820	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
821		if ((*strp++ = *keyid++) == IAC)
822			*strp++ = IAC;
823	}
824	*strp++ = IAC;
825	*strp++ = SE;
826	net_write(str_keyid, strp - str_keyid);
827	printsub('>', &str_keyid[2], strp - str_keyid - 2);
828}
829
830	void
831encrypt_auto(on)
832	int on;
833{
834	if (on < 0)
835		autoencrypt ^= 1;
836	else
837		autoencrypt = on ? 1 : 0;
838}
839
840	void
841decrypt_auto(on)
842	int on;
843{
844	if (on < 0)
845		autodecrypt ^= 1;
846	else
847		autodecrypt = on ? 1 : 0;
848}
849
850	void
851encrypt_start_output(type)
852	int type;
853{
854	Encryptions *ep;
855	register unsigned char *p;
856	register int i;
857
858	if (!(ep = findencryption(type))) {
859		if (encrypt_debug_mode) {
860			printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
861				Name,
862				ENCTYPE_NAME_OK(type)
863					? ENCTYPE_NAME(type) : "(unknown)",
864				type);
865		}
866		return;
867	}
868	if (ep->start) {
869		i = (*ep->start)(DIR_ENCRYPT, Server);
870		if (encrypt_debug_mode) {
871			printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
872				Name,
873				(i < 0) ? "failed" :
874					"initial negotiation in progress",
875				i, ENCTYPE_NAME(type));
876		}
877		if (i)
878			return;
879	}
880	p = str_start + 3;
881	*p++ = ENCRYPT_START;
882	for (i = 0; i < ki[0].keylen; ++i) {
883		if ((*p++ = ki[0].keyid[i]) == IAC)
884			*p++ = IAC;
885	}
886	*p++ = IAC;
887	*p++ = SE;
888	net_write(str_start, p - str_start);
889	net_encrypt();
890	printsub('>', &str_start[2], p - &str_start[2]);
891	/*
892	 * If we are already encrypting in some mode, then
893	 * encrypt the ring (which includes our request) in
894	 * the old mode, mark it all as "clear text" and then
895	 * switch to the new mode.
896	 */
897	encrypt_output = ep->output;
898	encrypt_mode = type;
899	if (encrypt_debug_mode)
900		printf(">>>%s: Started to encrypt output with type %s\r\n",
901			Name, ENCTYPE_NAME(type));
902	if (encrypt_verbose)
903		printf("[ Output is now encrypted with type %s ]\r\n",
904			ENCTYPE_NAME(type));
905}
906
907	void
908encrypt_send_end()
909{
910	if (!encrypt_output)
911		return;
912
913	str_end[3] = ENCRYPT_END;
914	net_write(str_end, sizeof(str_end));
915	net_encrypt();
916	printsub('>', &str_end[2], sizeof(str_end) - 2);
917	/*
918	 * Encrypt the output buffer now because it will not be done by
919	 * netflush...
920	 */
921	encrypt_output = 0;
922	if (encrypt_debug_mode)
923		printf(">>>%s: Output is back to clear text\r\n", Name);
924	if (encrypt_verbose)
925		printf("[ Output is now clear text ]\r\n");
926}
927
928	void
929encrypt_send_request_start()
930{
931	register unsigned char *p;
932	register int i;
933
934	p = &str_start[3];
935	*p++ = ENCRYPT_REQSTART;
936	for (i = 0; i < ki[1].keylen; ++i) {
937		if ((*p++ = ki[1].keyid[i]) == IAC)
938			*p++ = IAC;
939	}
940	*p++ = IAC;
941	*p++ = SE;
942	net_write(str_start, p - str_start);
943	printsub('>', &str_start[2], p - &str_start[2]);
944	if (encrypt_debug_mode)
945		printf(">>>%s: Request input to be encrypted\r\n", Name);
946}
947
948	void
949encrypt_send_request_end()
950{
951	str_end[3] = ENCRYPT_REQEND;
952	net_write(str_end, sizeof(str_end));
953	printsub('>', &str_end[2], sizeof(str_end) - 2);
954
955	if (encrypt_debug_mode)
956		printf(">>>%s: Request input to be clear text\r\n", Name);
957}
958
959	void
960encrypt_wait()
961{
962	if (encrypt_debug_mode)
963		printf(">>>%s: in encrypt_wait\r\n", Name);
964	if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
965		return;
966	while (autoencrypt && !encrypt_output)
967		if (telnet_spin())
968			return;
969}
970
971	void
972encrypt_debug(mode)
973	int mode;
974{
975	encrypt_debug_mode = mode;
976}
977
978	void
979encrypt_gen_printsub(data, cnt, buf, buflen)
980	unsigned char *data, *buf;
981	int cnt, buflen;
982{
983	char tbuf[16], *cp;
984
985	cnt -= 2;
986	data += 2;
987	buf[buflen-1] = '\0';
988	buf[buflen-2] = '*';
989	buflen -= 2;;
990	for (; cnt > 0; cnt--, data++) {
991		sprintf(tbuf, " %d", *data);
992		for (cp = tbuf; *cp && buflen > 0; --buflen)
993			*buf++ = *cp++;
994		if (buflen <= 0)
995			return;
996	}
997	*buf = '\0';
998}
999
1000	void
1001encrypt_printsub(data, cnt, buf, buflen)
1002	unsigned char *data, *buf;
1003	int cnt, buflen;
1004{
1005	Encryptions *ep;
1006	register int type = data[1];
1007
1008	for (ep = encryptions; ep->type && ep->type != type; ep++)
1009		;
1010
1011	if (ep->printsub)
1012		(*ep->printsub)(data, cnt, buf, buflen);
1013	else
1014		encrypt_gen_printsub(data, cnt, buf, buflen);
1015}
1016#endif	/* ENCRYPTION */
1017