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