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