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