xref: /freebsd/contrib/telnet/libtelnet/enc_des.c (revision 77b7cdf1999ee965ad494fddd184b18f532ac91a)
181cb6ddcSMark Murray /*-
281cb6ddcSMark Murray  * Copyright (c) 1991, 1993
381cb6ddcSMark Murray  *	The Regents of the University of California.  All rights reserved.
481cb6ddcSMark Murray  *
581cb6ddcSMark Murray  * Redistribution and use in source and binary forms, with or without
681cb6ddcSMark Murray  * modification, are permitted provided that the following conditions
781cb6ddcSMark Murray  * are met:
881cb6ddcSMark Murray  * 1. Redistributions of source code must retain the above copyright
981cb6ddcSMark Murray  *    notice, this list of conditions and the following disclaimer.
1081cb6ddcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
1181cb6ddcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
1281cb6ddcSMark Murray  *    documentation and/or other materials provided with the distribution.
1381cb6ddcSMark Murray  * 3. All advertising materials mentioning features or use of this software
1481cb6ddcSMark Murray  *    must display the following acknowledgement:
1581cb6ddcSMark Murray  *	This product includes software developed by the University of
1681cb6ddcSMark Murray  *	California, Berkeley and its contributors.
1781cb6ddcSMark Murray  * 4. Neither the name of the University nor the names of its contributors
1881cb6ddcSMark Murray  *    may be used to endorse or promote products derived from this software
1981cb6ddcSMark Murray  *    without specific prior written permission.
2081cb6ddcSMark Murray  *
2181cb6ddcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2281cb6ddcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2381cb6ddcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2481cb6ddcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2581cb6ddcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2681cb6ddcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2781cb6ddcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2881cb6ddcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2981cb6ddcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3081cb6ddcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3181cb6ddcSMark Murray  * SUCH DAMAGE.
3281cb6ddcSMark Murray  */
3381cb6ddcSMark Murray 
3477b7cdf1SDavid E. O'Brien #if 0
3581cb6ddcSMark Murray #ifndef lint
3604c426ccSMark Murray static const char sccsid[] = "@(#)enc_des.c	8.3 (Berkeley) 5/30/95";
3781cb6ddcSMark Murray #endif /* not lint */
3877b7cdf1SDavid E. O'Brien #endif
3977b7cdf1SDavid E. O'Brien #include <sys/cdefs.h>
4077b7cdf1SDavid E. O'Brien __FBSDID("$FreeBSD$");
4181cb6ddcSMark Murray 
4281cb6ddcSMark Murray #ifdef	ENCRYPTION
4381cb6ddcSMark Murray # ifdef	AUTHENTICATION
4481cb6ddcSMark Murray #include <arpa/telnet.h>
45bf4f84d4SMark Murray #include <openssl/des.h>
468fa113e5SMark Murray #include <stdio.h>
478fa113e5SMark Murray #include <stdlib.h>
4804c426ccSMark Murray #include <string.h>
498fa113e5SMark Murray 
5081cb6ddcSMark Murray #include "encrypt.h"
5181cb6ddcSMark Murray #include "key-proto.h"
5281cb6ddcSMark Murray #include "misc-proto.h"
5381cb6ddcSMark Murray 
5421f083c0SMark Murray extern int encrypt_debug_mode;
5581cb6ddcSMark Murray 
5681cb6ddcSMark Murray #define	CFB	0
5781cb6ddcSMark Murray #define	OFB	1
5881cb6ddcSMark Murray 
5981cb6ddcSMark Murray #define	NO_SEND_IV	1
6081cb6ddcSMark Murray #define	NO_RECV_IV	2
6181cb6ddcSMark Murray #define	NO_KEYID	4
6281cb6ddcSMark Murray #define	IN_PROGRESS	(NO_SEND_IV|NO_RECV_IV|NO_KEYID)
6381cb6ddcSMark Murray #define	SUCCESS		0
6481cb6ddcSMark Murray #define	FAILED		-1
6581cb6ddcSMark Murray 
6681cb6ddcSMark Murray 
6781cb6ddcSMark Murray struct fb {
6881cb6ddcSMark Murray 	Block krbdes_key;
6981cb6ddcSMark Murray 	Schedule krbdes_sched;
7081cb6ddcSMark Murray 	Block temp_feed;
7181cb6ddcSMark Murray 	unsigned char fb_feed[64];
7281cb6ddcSMark Murray 	int need_start;
7381cb6ddcSMark Murray 	int state[2];
7481cb6ddcSMark Murray 	int keyid[2];
7581cb6ddcSMark Murray 	struct stinfo {
7681cb6ddcSMark Murray 		Block		str_output;
7781cb6ddcSMark Murray 		Block		str_feed;
7881cb6ddcSMark Murray 		Block		str_iv;
7981cb6ddcSMark Murray 		Block		str_ikey;
8081cb6ddcSMark Murray 		Schedule	str_sched;
8181cb6ddcSMark Murray 		int		str_index;
8281cb6ddcSMark Murray 		int		str_flagshift;
8381cb6ddcSMark Murray 	} streams[2];
8481cb6ddcSMark Murray };
8581cb6ddcSMark Murray 
8681cb6ddcSMark Murray static struct fb fb[2];
8781cb6ddcSMark Murray 
8881cb6ddcSMark Murray struct keyidlist {
898fa113e5SMark Murray 	const char *keyid;
9081cb6ddcSMark Murray 	int	keyidlen;
9181cb6ddcSMark Murray 	char	*key;
9281cb6ddcSMark Murray 	int	keylen;
9381cb6ddcSMark Murray 	int	flags;
9481cb6ddcSMark Murray } keyidlist [] = {
9581cb6ddcSMark Murray 	{ "\0", 1, 0, 0, 0 },		/* default key of zero */
9681cb6ddcSMark Murray 	{ 0, 0, 0, 0, 0 }
9781cb6ddcSMark Murray };
9881cb6ddcSMark Murray 
9981cb6ddcSMark Murray #define	KEYFLAG_MASK	03
10081cb6ddcSMark Murray 
10181cb6ddcSMark Murray #define	KEYFLAG_NOINIT	00
10281cb6ddcSMark Murray #define	KEYFLAG_INIT	01
10381cb6ddcSMark Murray #define	KEYFLAG_OK	02
10481cb6ddcSMark Murray #define	KEYFLAG_BAD	03
10581cb6ddcSMark Murray 
10681cb6ddcSMark Murray #define	KEYFLAG_SHIFT	2
10781cb6ddcSMark Murray 
10881cb6ddcSMark Murray #define	SHIFT_VAL(a,b)	(KEYFLAG_SHIFT*((a)+((b)*2)))
10981cb6ddcSMark Murray 
11081cb6ddcSMark Murray #define	FB64_IV		1
11181cb6ddcSMark Murray #define	FB64_IV_OK	2
11281cb6ddcSMark Murray #define	FB64_IV_BAD	3
11381cb6ddcSMark Murray 
11481cb6ddcSMark Murray 
1153138440aSMark Murray void fb64_stream_iv(Block, struct stinfo *);
1163138440aSMark Murray void fb64_init(struct fb *);
1173138440aSMark Murray static int fb64_start(struct fb *, int, int);
1183138440aSMark Murray int fb64_is(unsigned char *, int, struct fb *);
1193138440aSMark Murray int fb64_reply(unsigned char *, int, struct fb *);
1203138440aSMark Murray static void fb64_session(Session_Key *, int, struct fb *);
1213138440aSMark Murray void fb64_stream_key(Block, struct stinfo *);
1223138440aSMark Murray int fb64_keyid(int, unsigned char *, int *, struct fb *);
12381cb6ddcSMark Murray 
12481cb6ddcSMark Murray void
1258fa113e5SMark Murray cfb64_init(int server __unused)
12681cb6ddcSMark Murray {
12781cb6ddcSMark Murray 	fb64_init(&fb[CFB]);
12881cb6ddcSMark Murray 	fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
12981cb6ddcSMark Murray 	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
13081cb6ddcSMark Murray 	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
13181cb6ddcSMark Murray }
13281cb6ddcSMark Murray 
13381cb6ddcSMark Murray void
1348fa113e5SMark Murray ofb64_init(int server __unused)
13581cb6ddcSMark Murray {
13681cb6ddcSMark Murray 	fb64_init(&fb[OFB]);
13781cb6ddcSMark Murray 	fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
13881cb6ddcSMark Murray 	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
13981cb6ddcSMark Murray 	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
14081cb6ddcSMark Murray }
14181cb6ddcSMark Murray 
14281cb6ddcSMark Murray void
1438fa113e5SMark Murray fb64_init(struct fb *fbp)
14481cb6ddcSMark Murray {
14581cb6ddcSMark Murray 	memset((void *)fbp, 0, sizeof(*fbp));
14681cb6ddcSMark Murray 	fbp->state[0] = fbp->state[1] = FAILED;
14781cb6ddcSMark Murray 	fbp->fb_feed[0] = IAC;
14881cb6ddcSMark Murray 	fbp->fb_feed[1] = SB;
14981cb6ddcSMark Murray 	fbp->fb_feed[2] = TELOPT_ENCRYPT;
15081cb6ddcSMark Murray 	fbp->fb_feed[3] = ENCRYPT_IS;
15181cb6ddcSMark Murray }
15281cb6ddcSMark Murray 
15381cb6ddcSMark Murray /*
15481cb6ddcSMark Murray  * Returns:
15581cb6ddcSMark Murray  *	-1: some error.  Negotiation is done, encryption not ready.
15681cb6ddcSMark Murray  *	 0: Successful, initial negotiation all done.
15781cb6ddcSMark Murray  *	 1: successful, negotiation not done yet.
15881cb6ddcSMark Murray  *	 2: Not yet.  Other things (like getting the key from
15981cb6ddcSMark Murray  *	    Kerberos) have to happen before we can continue.
16081cb6ddcSMark Murray  */
16181cb6ddcSMark Murray int
1628fa113e5SMark Murray cfb64_start(int dir, int server)
16381cb6ddcSMark Murray {
16481cb6ddcSMark Murray 	return(fb64_start(&fb[CFB], dir, server));
16581cb6ddcSMark Murray }
1668fa113e5SMark Murray 
16781cb6ddcSMark Murray int
1688fa113e5SMark Murray ofb64_start(int dir, int server)
16981cb6ddcSMark Murray {
17081cb6ddcSMark Murray 	return(fb64_start(&fb[OFB], dir, server));
17181cb6ddcSMark Murray }
17281cb6ddcSMark Murray 
17381cb6ddcSMark Murray static int
1748fa113e5SMark Murray fb64_start(struct fb *fbp, int dir, int server __unused)
17581cb6ddcSMark Murray {
1768fa113e5SMark Murray 	size_t x;
17781cb6ddcSMark Murray 	unsigned char *p;
1788fa113e5SMark Murray 	int state;
17981cb6ddcSMark Murray 
18081cb6ddcSMark Murray 	switch (dir) {
18181cb6ddcSMark Murray 	case DIR_DECRYPT:
18281cb6ddcSMark Murray 		/*
18381cb6ddcSMark Murray 		 * This is simply a request to have the other side
18481cb6ddcSMark Murray 		 * start output (our input).  He will negotiate an
18581cb6ddcSMark Murray 		 * IV so we need not look for it.
18681cb6ddcSMark Murray 		 */
18781cb6ddcSMark Murray 		state = fbp->state[dir-1];
18881cb6ddcSMark Murray 		if (state == FAILED)
18981cb6ddcSMark Murray 			state = IN_PROGRESS;
19081cb6ddcSMark Murray 		break;
19181cb6ddcSMark Murray 
19281cb6ddcSMark Murray 	case DIR_ENCRYPT:
19381cb6ddcSMark Murray 		state = fbp->state[dir-1];
19481cb6ddcSMark Murray 		if (state == FAILED)
19581cb6ddcSMark Murray 			state = IN_PROGRESS;
19681cb6ddcSMark Murray 		else if ((state & NO_SEND_IV) == 0)
19781cb6ddcSMark Murray 			break;
19881cb6ddcSMark Murray 
19981cb6ddcSMark Murray 		if (!VALIDKEY(fbp->krbdes_key)) {
20081cb6ddcSMark Murray 			fbp->need_start = 1;
20181cb6ddcSMark Murray 			break;
20281cb6ddcSMark Murray 		}
20381cb6ddcSMark Murray 		state &= ~NO_SEND_IV;
20481cb6ddcSMark Murray 		state |= NO_RECV_IV;
20581cb6ddcSMark Murray 		if (encrypt_debug_mode)
20681cb6ddcSMark Murray 			printf("Creating new feed\r\n");
20781cb6ddcSMark Murray 		/*
20881cb6ddcSMark Murray 		 * Create a random feed and send it over.
20981cb6ddcSMark Murray 		 */
2104b2eaea4SJacques Vidrine 		des_random_key((Block *)fbp->temp_feed);
21104c426ccSMark Murray 		des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed,
21281cb6ddcSMark Murray 				fbp->krbdes_sched, 1);
21381cb6ddcSMark Murray 		p = fbp->fb_feed + 3;
21481cb6ddcSMark Murray 		*p++ = ENCRYPT_IS;
21581cb6ddcSMark Murray 		p++;
21681cb6ddcSMark Murray 		*p++ = FB64_IV;
21781cb6ddcSMark Murray 		for (x = 0; x < sizeof(Block); ++x) {
21881cb6ddcSMark Murray 			if ((*p++ = fbp->temp_feed[x]) == IAC)
21981cb6ddcSMark Murray 				*p++ = IAC;
22081cb6ddcSMark Murray 		}
22181cb6ddcSMark Murray 		*p++ = IAC;
22281cb6ddcSMark Murray 		*p++ = SE;
22381cb6ddcSMark Murray 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
22481cb6ddcSMark Murray 		net_write(fbp->fb_feed, p - fbp->fb_feed);
22581cb6ddcSMark Murray 		break;
22681cb6ddcSMark Murray 	default:
22781cb6ddcSMark Murray 		return(FAILED);
22881cb6ddcSMark Murray 	}
22981cb6ddcSMark Murray 	return(fbp->state[dir-1] = state);
23081cb6ddcSMark Murray }
23181cb6ddcSMark Murray 
23281cb6ddcSMark Murray /*
23381cb6ddcSMark Murray  * Returns:
23481cb6ddcSMark Murray  *	-1: some error.  Negotiation is done, encryption not ready.
23581cb6ddcSMark Murray  *	 0: Successful, initial negotiation all done.
23681cb6ddcSMark Murray  *	 1: successful, negotiation not done yet.
23781cb6ddcSMark Murray  */
23881cb6ddcSMark Murray int
2398fa113e5SMark Murray cfb64_is(unsigned char *data, int cnt)
24081cb6ddcSMark Murray {
24181cb6ddcSMark Murray 	return(fb64_is(data, cnt, &fb[CFB]));
24281cb6ddcSMark Murray }
2438fa113e5SMark Murray 
24481cb6ddcSMark Murray int
2458fa113e5SMark Murray ofb64_is(unsigned char *data, int cnt)
24681cb6ddcSMark Murray {
24781cb6ddcSMark Murray 	return(fb64_is(data, cnt, &fb[OFB]));
24881cb6ddcSMark Murray }
24981cb6ddcSMark Murray 
25081cb6ddcSMark Murray int
2518fa113e5SMark Murray fb64_is(unsigned char *data, int cnt, struct fb *fbp)
25281cb6ddcSMark Murray {
25381cb6ddcSMark Murray 	unsigned char *p;
2548fa113e5SMark Murray 	int state = fbp->state[DIR_DECRYPT-1];
25581cb6ddcSMark Murray 
25681cb6ddcSMark Murray 	if (cnt-- < 1)
25781cb6ddcSMark Murray 		goto failure;
25881cb6ddcSMark Murray 
25981cb6ddcSMark Murray 	switch (*data++) {
26081cb6ddcSMark Murray 	case FB64_IV:
26181cb6ddcSMark Murray 		if (cnt != sizeof(Block)) {
26281cb6ddcSMark Murray 			if (encrypt_debug_mode)
26381cb6ddcSMark Murray 				printf("CFB64: initial vector failed on size\r\n");
26481cb6ddcSMark Murray 			state = FAILED;
26581cb6ddcSMark Murray 			goto failure;
26681cb6ddcSMark Murray 		}
26781cb6ddcSMark Murray 
26881cb6ddcSMark Murray 		if (encrypt_debug_mode)
26981cb6ddcSMark Murray 			printf("CFB64: initial vector received\r\n");
27081cb6ddcSMark Murray 
27181cb6ddcSMark Murray 		if (encrypt_debug_mode)
27281cb6ddcSMark Murray 			printf("Initializing Decrypt stream\r\n");
27381cb6ddcSMark Murray 
27481cb6ddcSMark Murray 		fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
27581cb6ddcSMark Murray 
27681cb6ddcSMark Murray 		p = fbp->fb_feed + 3;
27781cb6ddcSMark Murray 		*p++ = ENCRYPT_REPLY;
27881cb6ddcSMark Murray 		p++;
27981cb6ddcSMark Murray 		*p++ = FB64_IV_OK;
28081cb6ddcSMark Murray 		*p++ = IAC;
28181cb6ddcSMark Murray 		*p++ = SE;
28281cb6ddcSMark Murray 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
28381cb6ddcSMark Murray 		net_write(fbp->fb_feed, p - fbp->fb_feed);
28481cb6ddcSMark Murray 
28581cb6ddcSMark Murray 		state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
28681cb6ddcSMark Murray 		break;
28781cb6ddcSMark Murray 
28881cb6ddcSMark Murray 	default:
28981cb6ddcSMark Murray 		if (encrypt_debug_mode) {
29081cb6ddcSMark Murray 			printf("Unknown option type: %d\r\n", *(data-1));
29181cb6ddcSMark Murray 			printd(data, cnt);
29281cb6ddcSMark Murray 			printf("\r\n");
29381cb6ddcSMark Murray 		}
29481cb6ddcSMark Murray 		/* FALL THROUGH */
29581cb6ddcSMark Murray 	failure:
29681cb6ddcSMark Murray 		/*
29781cb6ddcSMark Murray 		 * We failed.  Send an FB64_IV_BAD option
29881cb6ddcSMark Murray 		 * to the other side so it will know that
29981cb6ddcSMark Murray 		 * things failed.
30081cb6ddcSMark Murray 		 */
30181cb6ddcSMark Murray 		p = fbp->fb_feed + 3;
30281cb6ddcSMark Murray 		*p++ = ENCRYPT_REPLY;
30381cb6ddcSMark Murray 		p++;
30481cb6ddcSMark Murray 		*p++ = FB64_IV_BAD;
30581cb6ddcSMark Murray 		*p++ = IAC;
30681cb6ddcSMark Murray 		*p++ = SE;
30781cb6ddcSMark Murray 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
30881cb6ddcSMark Murray 		net_write(fbp->fb_feed, p - fbp->fb_feed);
30981cb6ddcSMark Murray 
31081cb6ddcSMark Murray 		break;
31181cb6ddcSMark Murray 	}
31281cb6ddcSMark Murray 	return(fbp->state[DIR_DECRYPT-1] = state);
31381cb6ddcSMark Murray }
31481cb6ddcSMark Murray 
31581cb6ddcSMark Murray /*
31681cb6ddcSMark Murray  * Returns:
31781cb6ddcSMark Murray  *	-1: some error.  Negotiation is done, encryption not ready.
31881cb6ddcSMark Murray  *	 0: Successful, initial negotiation all done.
31981cb6ddcSMark Murray  *	 1: successful, negotiation not done yet.
32081cb6ddcSMark Murray  */
32181cb6ddcSMark Murray int
3228fa113e5SMark Murray cfb64_reply(unsigned char *data, int cnt)
32381cb6ddcSMark Murray {
32481cb6ddcSMark Murray 	return(fb64_reply(data, cnt, &fb[CFB]));
32581cb6ddcSMark Murray }
3268fa113e5SMark Murray 
32781cb6ddcSMark Murray int
3288fa113e5SMark Murray ofb64_reply(unsigned char *data, int cnt)
32981cb6ddcSMark Murray {
33081cb6ddcSMark Murray 	return(fb64_reply(data, cnt, &fb[OFB]));
33181cb6ddcSMark Murray }
33281cb6ddcSMark Murray 
33381cb6ddcSMark Murray int
3348fa113e5SMark Murray fb64_reply(unsigned char *data, int cnt, struct fb *fbp)
33581cb6ddcSMark Murray {
3368fa113e5SMark Murray 	int state = fbp->state[DIR_ENCRYPT-1];
33781cb6ddcSMark Murray 
33881cb6ddcSMark Murray 	if (cnt-- < 1)
33981cb6ddcSMark Murray 		goto failure;
34081cb6ddcSMark Murray 
34181cb6ddcSMark Murray 	switch (*data++) {
34281cb6ddcSMark Murray 	case FB64_IV_OK:
34381cb6ddcSMark Murray 		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
34481cb6ddcSMark Murray 		if (state == FAILED)
34581cb6ddcSMark Murray 			state = IN_PROGRESS;
34681cb6ddcSMark Murray 		state &= ~NO_RECV_IV;
3478fa113e5SMark Murray 		encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1);
34881cb6ddcSMark Murray 		break;
34981cb6ddcSMark Murray 
35081cb6ddcSMark Murray 	case FB64_IV_BAD:
35181cb6ddcSMark Murray 		memset(fbp->temp_feed, 0, sizeof(Block));
35281cb6ddcSMark Murray 		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
35381cb6ddcSMark Murray 		state = FAILED;
35481cb6ddcSMark Murray 		break;
35581cb6ddcSMark Murray 
35681cb6ddcSMark Murray 	default:
35781cb6ddcSMark Murray 		if (encrypt_debug_mode) {
35881cb6ddcSMark Murray 			printf("Unknown option type: %d\r\n", data[-1]);
35981cb6ddcSMark Murray 			printd(data, cnt);
36081cb6ddcSMark Murray 			printf("\r\n");
36181cb6ddcSMark Murray 		}
36281cb6ddcSMark Murray 		/* FALL THROUGH */
36381cb6ddcSMark Murray 	failure:
36481cb6ddcSMark Murray 		state = FAILED;
36581cb6ddcSMark Murray 		break;
36681cb6ddcSMark Murray 	}
36781cb6ddcSMark Murray 	return(fbp->state[DIR_ENCRYPT-1] = state);
36881cb6ddcSMark Murray }
36981cb6ddcSMark Murray 
37081cb6ddcSMark Murray void
3718fa113e5SMark Murray cfb64_session(Session_Key *key, int server)
37281cb6ddcSMark Murray {
37381cb6ddcSMark Murray 	fb64_session(key, server, &fb[CFB]);
37481cb6ddcSMark Murray }
37581cb6ddcSMark Murray 
37681cb6ddcSMark Murray void
3778fa113e5SMark Murray ofb64_session(Session_Key *key, int server)
37881cb6ddcSMark Murray {
37981cb6ddcSMark Murray 	fb64_session(key, server, &fb[OFB]);
38081cb6ddcSMark Murray }
38181cb6ddcSMark Murray 
38281cb6ddcSMark Murray static void
3838fa113e5SMark Murray fb64_session(Session_Key *key, int server, struct fb *fbp)
38481cb6ddcSMark Murray {
38581cb6ddcSMark Murray 	if (!key || key->type != SK_DES) {
38681cb6ddcSMark Murray 		if (encrypt_debug_mode)
38781cb6ddcSMark Murray 			printf("Can't set krbdes's session key (%d != %d)\r\n",
38881cb6ddcSMark Murray 				key ? key->type : -1, SK_DES);
38981cb6ddcSMark Murray 		return;
39081cb6ddcSMark Murray 	}
39181cb6ddcSMark Murray 	memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
39281cb6ddcSMark Murray 
39381cb6ddcSMark Murray 	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
39481cb6ddcSMark Murray 	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
39581cb6ddcSMark Murray 
39604c426ccSMark Murray 	des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched);
39781cb6ddcSMark Murray 	/*
39881cb6ddcSMark Murray 	 * Now look to see if krbdes_start() was was waiting for
39981cb6ddcSMark Murray 	 * the key to show up.  If so, go ahead an call it now
40081cb6ddcSMark Murray 	 * that we have the key.
40181cb6ddcSMark Murray 	 */
40281cb6ddcSMark Murray 	if (fbp->need_start) {
40381cb6ddcSMark Murray 		fbp->need_start = 0;
40481cb6ddcSMark Murray 		fb64_start(fbp, DIR_ENCRYPT, server);
40581cb6ddcSMark Murray 	}
40681cb6ddcSMark Murray }
40781cb6ddcSMark Murray 
40881cb6ddcSMark Murray /*
40981cb6ddcSMark Murray  * We only accept a keyid of 0.  If we get a keyid of
41081cb6ddcSMark Murray  * 0, then mark the state as SUCCESS.
41181cb6ddcSMark Murray  */
41281cb6ddcSMark Murray int
4138fa113e5SMark Murray cfb64_keyid(int dir, unsigned char *kp, int *lenp)
41481cb6ddcSMark Murray {
41581cb6ddcSMark Murray 	return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
41681cb6ddcSMark Murray }
41781cb6ddcSMark Murray 
41881cb6ddcSMark Murray int
4198fa113e5SMark Murray ofb64_keyid(int dir, unsigned char *kp, int *lenp)
42081cb6ddcSMark Murray {
42181cb6ddcSMark Murray 	return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
42281cb6ddcSMark Murray }
42381cb6ddcSMark Murray 
42481cb6ddcSMark Murray int
4258fa113e5SMark Murray fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp)
42681cb6ddcSMark Murray {
4278fa113e5SMark Murray 	int state = fbp->state[dir-1];
42881cb6ddcSMark Murray 
42981cb6ddcSMark Murray 	if (*lenp != 1 || (*kp != '\0')) {
43081cb6ddcSMark Murray 		*lenp = 0;
43181cb6ddcSMark Murray 		return(state);
43281cb6ddcSMark Murray 	}
43381cb6ddcSMark Murray 
43481cb6ddcSMark Murray 	if (state == FAILED)
43581cb6ddcSMark Murray 		state = IN_PROGRESS;
43681cb6ddcSMark Murray 
43781cb6ddcSMark Murray 	state &= ~NO_KEYID;
43881cb6ddcSMark Murray 
43981cb6ddcSMark Murray 	return(fbp->state[dir-1] = state);
44081cb6ddcSMark Murray }
44181cb6ddcSMark Murray 
44281cb6ddcSMark Murray void
4438fa113e5SMark Murray fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type)
44481cb6ddcSMark Murray {
44581cb6ddcSMark Murray 	char lbuf[32];
4468fa113e5SMark Murray 	int i;
44781cb6ddcSMark Murray 	char *cp;
44881cb6ddcSMark Murray 
44981cb6ddcSMark Murray 	buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
45081cb6ddcSMark Murray 	buflen -= 1;
45181cb6ddcSMark Murray 
45281cb6ddcSMark Murray 	switch(data[2]) {
45381cb6ddcSMark Murray 	case FB64_IV:
45481cb6ddcSMark Murray 		sprintf(lbuf, "%s_IV", type);
45581cb6ddcSMark Murray 		cp = lbuf;
45681cb6ddcSMark Murray 		goto common;
45781cb6ddcSMark Murray 
45881cb6ddcSMark Murray 	case FB64_IV_OK:
45981cb6ddcSMark Murray 		sprintf(lbuf, "%s_IV_OK", type);
46081cb6ddcSMark Murray 		cp = lbuf;
46181cb6ddcSMark Murray 		goto common;
46281cb6ddcSMark Murray 
46381cb6ddcSMark Murray 	case FB64_IV_BAD:
46481cb6ddcSMark Murray 		sprintf(lbuf, "%s_IV_BAD", type);
46581cb6ddcSMark Murray 		cp = lbuf;
46681cb6ddcSMark Murray 		goto common;
46781cb6ddcSMark Murray 
46881cb6ddcSMark Murray 	default:
46981cb6ddcSMark Murray 		sprintf(lbuf, " %d (unknown)", data[2]);
47081cb6ddcSMark Murray 		cp = lbuf;
47181cb6ddcSMark Murray 	common:
47281cb6ddcSMark Murray 		for (; (buflen > 0) && (*buf = *cp++); buf++)
47381cb6ddcSMark Murray 			buflen--;
47481cb6ddcSMark Murray 		for (i = 3; i < cnt; i++) {
47581cb6ddcSMark Murray 			sprintf(lbuf, " %d", data[i]);
47681cb6ddcSMark Murray 			for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
47781cb6ddcSMark Murray 				buflen--;
47881cb6ddcSMark Murray 		}
47981cb6ddcSMark Murray 		break;
48081cb6ddcSMark Murray 	}
48181cb6ddcSMark Murray }
48281cb6ddcSMark Murray 
48381cb6ddcSMark Murray void
4848fa113e5SMark Murray cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
48581cb6ddcSMark Murray {
48681cb6ddcSMark Murray 	fb64_printsub(data, cnt, buf, buflen, "CFB64");
48781cb6ddcSMark Murray }
48881cb6ddcSMark Murray 
48981cb6ddcSMark Murray void
4908fa113e5SMark Murray ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
49181cb6ddcSMark Murray {
49281cb6ddcSMark Murray 	fb64_printsub(data, cnt, buf, buflen, "OFB64");
49381cb6ddcSMark Murray }
49481cb6ddcSMark Murray 
49581cb6ddcSMark Murray void
4968fa113e5SMark Murray fb64_stream_iv(Block seed, struct stinfo *stp)
49781cb6ddcSMark Murray {
49881cb6ddcSMark Murray 
49981cb6ddcSMark Murray 	memmove((void *)stp->str_iv, (void *)seed, sizeof(Block));
50081cb6ddcSMark Murray 	memmove((void *)stp->str_output, (void *)seed, sizeof(Block));
50181cb6ddcSMark Murray 
50204c426ccSMark Murray 	des_key_sched((Block *)stp->str_ikey, stp->str_sched);
50381cb6ddcSMark Murray 
50481cb6ddcSMark Murray 	stp->str_index = sizeof(Block);
50581cb6ddcSMark Murray }
50681cb6ddcSMark Murray 
50781cb6ddcSMark Murray void
5088fa113e5SMark Murray fb64_stream_key(Block key, struct stinfo *stp)
50981cb6ddcSMark Murray {
51081cb6ddcSMark Murray 	memmove((void *)stp->str_ikey, (void *)key, sizeof(Block));
51104c426ccSMark Murray 	des_key_sched((Block *)key, stp->str_sched);
51281cb6ddcSMark Murray 
51381cb6ddcSMark Murray 	memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
51481cb6ddcSMark Murray 
51581cb6ddcSMark Murray 	stp->str_index = sizeof(Block);
51681cb6ddcSMark Murray }
51781cb6ddcSMark Murray 
51881cb6ddcSMark Murray /*
51981cb6ddcSMark Murray  * DES 64 bit Cipher Feedback
52081cb6ddcSMark Murray  *
52181cb6ddcSMark Murray  *     key --->+-----+
52281cb6ddcSMark Murray  *          +->| DES |--+
52381cb6ddcSMark Murray  *          |  +-----+  |
52481cb6ddcSMark Murray  *	    |           v
52581cb6ddcSMark Murray  *  INPUT --(--------->(+)+---> DATA
52681cb6ddcSMark Murray  *          |             |
52781cb6ddcSMark Murray  *	    +-------------+
52881cb6ddcSMark Murray  *
52981cb6ddcSMark Murray  *
53081cb6ddcSMark Murray  * Given:
53181cb6ddcSMark Murray  *	iV: Initial vector, 64 bits (8 bytes) long.
53281cb6ddcSMark Murray  *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
53381cb6ddcSMark Murray  *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
53481cb6ddcSMark Murray  *
53581cb6ddcSMark Murray  *	V0 = DES(iV, key)
53681cb6ddcSMark Murray  *	On = Dn ^ Vn
53781cb6ddcSMark Murray  *	V(n+1) = DES(On, key)
53881cb6ddcSMark Murray  */
53981cb6ddcSMark Murray 
54081cb6ddcSMark Murray void
5418fa113e5SMark Murray cfb64_encrypt(unsigned char *s, int c)
54281cb6ddcSMark Murray {
5438fa113e5SMark Murray 	struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
5448fa113e5SMark Murray 	int idx;
54581cb6ddcSMark Murray 
5468fa113e5SMark Murray 	idx = stp->str_index;
54781cb6ddcSMark Murray 	while (c-- > 0) {
5488fa113e5SMark Murray 		if (idx == sizeof(Block)) {
54981cb6ddcSMark Murray 			Block b;
55004c426ccSMark Murray 			des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
55181cb6ddcSMark Murray 			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
5528fa113e5SMark Murray 			idx = 0;
55381cb6ddcSMark Murray 		}
55481cb6ddcSMark Murray 
55581cb6ddcSMark Murray 		/* On encryption, we store (feed ^ data) which is cypher */
5568fa113e5SMark Murray 		*s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s);
55781cb6ddcSMark Murray 		s++;
5588fa113e5SMark Murray 		idx++;
55981cb6ddcSMark Murray 	}
5608fa113e5SMark Murray 	stp->str_index = idx;
56181cb6ddcSMark Murray }
56281cb6ddcSMark Murray 
56381cb6ddcSMark Murray int
5648fa113e5SMark Murray cfb64_decrypt(int data)
56581cb6ddcSMark Murray {
5668fa113e5SMark Murray 	struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
5678fa113e5SMark Murray 	int idx;
56881cb6ddcSMark Murray 
56981cb6ddcSMark Murray 	if (data == -1) {
57081cb6ddcSMark Murray 		/*
57181cb6ddcSMark Murray 		 * Back up one byte.  It is assumed that we will
57281cb6ddcSMark Murray 		 * never back up more than one byte.  If we do, this
57381cb6ddcSMark Murray 		 * may or may not work.
57481cb6ddcSMark Murray 		 */
57581cb6ddcSMark Murray 		if (stp->str_index)
57681cb6ddcSMark Murray 			--stp->str_index;
57781cb6ddcSMark Murray 		return(0);
57881cb6ddcSMark Murray 	}
57981cb6ddcSMark Murray 
5808fa113e5SMark Murray 	idx = stp->str_index++;
5818fa113e5SMark Murray 	if (idx == sizeof(Block)) {
58281cb6ddcSMark Murray 		Block b;
58304c426ccSMark Murray 		des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
58481cb6ddcSMark Murray 		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
58581cb6ddcSMark Murray 		stp->str_index = 1;	/* Next time will be 1 */
5868fa113e5SMark Murray 		idx = 0;		/* But now use 0 */
58781cb6ddcSMark Murray 	}
58881cb6ddcSMark Murray 
58981cb6ddcSMark Murray 	/* On decryption we store (data) which is cypher. */
5908fa113e5SMark Murray 	stp->str_output[idx] = data;
5918fa113e5SMark Murray 	return(data ^ stp->str_feed[idx]);
59281cb6ddcSMark Murray }
59381cb6ddcSMark Murray 
59481cb6ddcSMark Murray /*
59581cb6ddcSMark Murray  * DES 64 bit Output Feedback
59681cb6ddcSMark Murray  *
59781cb6ddcSMark Murray  * key --->+-----+
59881cb6ddcSMark Murray  *	+->| DES |--+
59981cb6ddcSMark Murray  *	|  +-----+  |
60081cb6ddcSMark Murray  *	+-----------+
60181cb6ddcSMark Murray  *	            v
60281cb6ddcSMark Murray  *  INPUT -------->(+) ----> DATA
60381cb6ddcSMark Murray  *
60481cb6ddcSMark Murray  * Given:
60581cb6ddcSMark Murray  *	iV: Initial vector, 64 bits (8 bytes) long.
60681cb6ddcSMark Murray  *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
60781cb6ddcSMark Murray  *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
60881cb6ddcSMark Murray  *
60981cb6ddcSMark Murray  *	V0 = DES(iV, key)
61081cb6ddcSMark Murray  *	V(n+1) = DES(Vn, key)
61181cb6ddcSMark Murray  *	On = Dn ^ Vn
61281cb6ddcSMark Murray  */
61381cb6ddcSMark Murray void
6148fa113e5SMark Murray ofb64_encrypt(unsigned char *s, int c)
61581cb6ddcSMark Murray {
6168fa113e5SMark Murray 	struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
6178fa113e5SMark Murray 	int idx;
61881cb6ddcSMark Murray 
6198fa113e5SMark Murray 	idx = stp->str_index;
62081cb6ddcSMark Murray 	while (c-- > 0) {
6218fa113e5SMark Murray 		if (idx == sizeof(Block)) {
62281cb6ddcSMark Murray 			Block b;
62304c426ccSMark Murray 			des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
62481cb6ddcSMark Murray 			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
6258fa113e5SMark Murray 			idx = 0;
62681cb6ddcSMark Murray 		}
6278fa113e5SMark Murray 		*s++ ^= stp->str_feed[idx];
6288fa113e5SMark Murray 		idx++;
62981cb6ddcSMark Murray 	}
6308fa113e5SMark Murray 	stp->str_index = idx;
63181cb6ddcSMark Murray }
63281cb6ddcSMark Murray 
63381cb6ddcSMark Murray int
6348fa113e5SMark Murray ofb64_decrypt(int data)
63581cb6ddcSMark Murray {
6368fa113e5SMark Murray 	struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
6378fa113e5SMark Murray 	int idx;
63881cb6ddcSMark Murray 
63981cb6ddcSMark Murray 	if (data == -1) {
64081cb6ddcSMark Murray 		/*
64181cb6ddcSMark Murray 		 * Back up one byte.  It is assumed that we will
64281cb6ddcSMark Murray 		 * never back up more than one byte.  If we do, this
64381cb6ddcSMark Murray 		 * may or may not work.
64481cb6ddcSMark Murray 		 */
64581cb6ddcSMark Murray 		if (stp->str_index)
64681cb6ddcSMark Murray 			--stp->str_index;
64781cb6ddcSMark Murray 		return(0);
64881cb6ddcSMark Murray 	}
64981cb6ddcSMark Murray 
6508fa113e5SMark Murray 	idx = stp->str_index++;
6518fa113e5SMark Murray 	if (idx == sizeof(Block)) {
65281cb6ddcSMark Murray 		Block b;
65304c426ccSMark Murray 		des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
65481cb6ddcSMark Murray 		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
65581cb6ddcSMark Murray 		stp->str_index = 1;	/* Next time will be 1 */
6568fa113e5SMark Murray 		idx = 0;		/* But now use 0 */
65781cb6ddcSMark Murray 	}
65881cb6ddcSMark Murray 
6598fa113e5SMark Murray 	return(data ^ stp->str_feed[idx]);
66081cb6ddcSMark Murray }
66181cb6ddcSMark Murray # endif	/* AUTHENTICATION */
66281cb6ddcSMark Murray #endif	/* ENCRYPTION */
663