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