xref: /freebsd/contrib/telnet/libtelnet/enc_des.c (revision a3c858005cae175e277f6f6735ca9eaea7eaf3c3)
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.
13*83129c0bSEd Maste  * 3. Neither the name of the University nor the names of its contributors
1481cb6ddcSMark Murray  *    may be used to endorse or promote products derived from this software
1581cb6ddcSMark Murray  *    without specific prior written permission.
1681cb6ddcSMark Murray  *
1781cb6ddcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1881cb6ddcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1981cb6ddcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2081cb6ddcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2181cb6ddcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2281cb6ddcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2381cb6ddcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2481cb6ddcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2581cb6ddcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2681cb6ddcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2781cb6ddcSMark Murray  * SUCH DAMAGE.
2881cb6ddcSMark Murray  */
2981cb6ddcSMark Murray 
3077b7cdf1SDavid E. O'Brien #if 0
3181cb6ddcSMark Murray #ifndef lint
3204c426ccSMark Murray static const char sccsid[] = "@(#)enc_des.c	8.3 (Berkeley) 5/30/95";
3381cb6ddcSMark Murray #endif /* not lint */
3477b7cdf1SDavid E. O'Brien #endif
3581cb6ddcSMark Murray 
3681cb6ddcSMark Murray #ifdef	ENCRYPTION
3781cb6ddcSMark Murray # ifdef	AUTHENTICATION
3881cb6ddcSMark Murray #include <arpa/telnet.h>
39bf4f84d4SMark Murray #include <openssl/des.h>
408fa113e5SMark Murray #include <stdio.h>
418fa113e5SMark Murray #include <stdlib.h>
4204c426ccSMark Murray #include <string.h>
438fa113e5SMark Murray 
4481cb6ddcSMark Murray #include "encrypt.h"
4581cb6ddcSMark Murray #include "key-proto.h"
4681cb6ddcSMark Murray #include "misc-proto.h"
4781cb6ddcSMark Murray 
4821f083c0SMark Murray extern int encrypt_debug_mode;
4981cb6ddcSMark Murray 
5081cb6ddcSMark Murray #define	CFB	0
5181cb6ddcSMark Murray #define	OFB	1
5281cb6ddcSMark Murray 
5381cb6ddcSMark Murray #define	NO_SEND_IV	1
5481cb6ddcSMark Murray #define	NO_RECV_IV	2
5581cb6ddcSMark Murray #define	NO_KEYID	4
5681cb6ddcSMark Murray #define	IN_PROGRESS	(NO_SEND_IV|NO_RECV_IV|NO_KEYID)
5781cb6ddcSMark Murray #define	SUCCESS		0
5881cb6ddcSMark Murray #define	FAILED		-1
5981cb6ddcSMark Murray 
6081cb6ddcSMark Murray 
6181cb6ddcSMark Murray struct fb {
6281cb6ddcSMark Murray 	Block krbdes_key;
6381cb6ddcSMark Murray 	Schedule krbdes_sched;
6481cb6ddcSMark Murray 	Block temp_feed;
6581cb6ddcSMark Murray 	unsigned char fb_feed[64];
6681cb6ddcSMark Murray 	int need_start;
6781cb6ddcSMark Murray 	int state[2];
6881cb6ddcSMark Murray 	int keyid[2];
6981cb6ddcSMark Murray 	struct stinfo {
7081cb6ddcSMark Murray 		Block		str_output;
7181cb6ddcSMark Murray 		Block		str_feed;
7281cb6ddcSMark Murray 		Block		str_iv;
7381cb6ddcSMark Murray 		Block		str_ikey;
7481cb6ddcSMark Murray 		Schedule	str_sched;
7581cb6ddcSMark Murray 		int		str_index;
7681cb6ddcSMark Murray 		int		str_flagshift;
7781cb6ddcSMark Murray 	} streams[2];
7881cb6ddcSMark Murray };
7981cb6ddcSMark Murray 
8081cb6ddcSMark Murray static struct fb fb[2];
8181cb6ddcSMark Murray 
8281cb6ddcSMark Murray struct keyidlist {
838fa113e5SMark Murray 	const char *keyid;
8481cb6ddcSMark Murray 	int	keyidlen;
8581cb6ddcSMark Murray 	char	*key;
8681cb6ddcSMark Murray 	int	keylen;
8781cb6ddcSMark Murray 	int	flags;
8881cb6ddcSMark Murray } keyidlist [] = {
8981cb6ddcSMark Murray 	{ "\0", 1, 0, 0, 0 },		/* default key of zero */
9081cb6ddcSMark Murray 	{ 0, 0, 0, 0, 0 }
9181cb6ddcSMark Murray };
9281cb6ddcSMark Murray 
9381cb6ddcSMark Murray #define	KEYFLAG_MASK	03
9481cb6ddcSMark Murray 
9581cb6ddcSMark Murray #define	KEYFLAG_NOINIT	00
9681cb6ddcSMark Murray #define	KEYFLAG_INIT	01
9781cb6ddcSMark Murray #define	KEYFLAG_OK	02
9881cb6ddcSMark Murray #define	KEYFLAG_BAD	03
9981cb6ddcSMark Murray 
10081cb6ddcSMark Murray #define	KEYFLAG_SHIFT	2
10181cb6ddcSMark Murray 
10281cb6ddcSMark Murray #define	SHIFT_VAL(a,b)	(KEYFLAG_SHIFT*((a)+((b)*2)))
10381cb6ddcSMark Murray 
10481cb6ddcSMark Murray #define	FB64_IV		1
10581cb6ddcSMark Murray #define	FB64_IV_OK	2
10681cb6ddcSMark Murray #define	FB64_IV_BAD	3
10781cb6ddcSMark Murray 
10881cb6ddcSMark Murray 
1093138440aSMark Murray void fb64_stream_iv(Block, struct stinfo *);
1103138440aSMark Murray void fb64_init(struct fb *);
1113138440aSMark Murray static int fb64_start(struct fb *, int, int);
1123138440aSMark Murray int fb64_is(unsigned char *, int, struct fb *);
1133138440aSMark Murray int fb64_reply(unsigned char *, int, struct fb *);
1143138440aSMark Murray static void fb64_session(Session_Key *, int, struct fb *);
1153138440aSMark Murray void fb64_stream_key(Block, struct stinfo *);
1163138440aSMark Murray int fb64_keyid(int, unsigned char *, int *, struct fb *);
11781cb6ddcSMark Murray 
11881cb6ddcSMark Murray void
cfb64_init(int server __unused)1198fa113e5SMark Murray cfb64_init(int server __unused)
12081cb6ddcSMark Murray {
12181cb6ddcSMark Murray 	fb64_init(&fb[CFB]);
12281cb6ddcSMark Murray 	fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
12381cb6ddcSMark Murray 	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
12481cb6ddcSMark Murray 	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
12581cb6ddcSMark Murray }
12681cb6ddcSMark Murray 
12781cb6ddcSMark Murray void
ofb64_init(int server __unused)1288fa113e5SMark Murray ofb64_init(int server __unused)
12981cb6ddcSMark Murray {
13081cb6ddcSMark Murray 	fb64_init(&fb[OFB]);
13181cb6ddcSMark Murray 	fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
13281cb6ddcSMark Murray 	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
13381cb6ddcSMark Murray 	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
13481cb6ddcSMark Murray }
13581cb6ddcSMark Murray 
13681cb6ddcSMark Murray void
fb64_init(struct fb * fbp)1378fa113e5SMark Murray fb64_init(struct fb *fbp)
13881cb6ddcSMark Murray {
13981cb6ddcSMark Murray 	memset((void *)fbp, 0, sizeof(*fbp));
14081cb6ddcSMark Murray 	fbp->state[0] = fbp->state[1] = FAILED;
14181cb6ddcSMark Murray 	fbp->fb_feed[0] = IAC;
14281cb6ddcSMark Murray 	fbp->fb_feed[1] = SB;
14381cb6ddcSMark Murray 	fbp->fb_feed[2] = TELOPT_ENCRYPT;
14481cb6ddcSMark Murray 	fbp->fb_feed[3] = ENCRYPT_IS;
14581cb6ddcSMark Murray }
14681cb6ddcSMark Murray 
14781cb6ddcSMark Murray /*
14881cb6ddcSMark Murray  * Returns:
14981cb6ddcSMark Murray  *	-1: some error.  Negotiation is done, encryption not ready.
15081cb6ddcSMark Murray  *	 0: Successful, initial negotiation all done.
15181cb6ddcSMark Murray  *	 1: successful, negotiation not done yet.
15281cb6ddcSMark Murray  *	 2: Not yet.  Other things (like getting the key from
15381cb6ddcSMark Murray  *	    Kerberos) have to happen before we can continue.
15481cb6ddcSMark Murray  */
15581cb6ddcSMark Murray int
cfb64_start(int dir,int server)1568fa113e5SMark Murray cfb64_start(int dir, int server)
15781cb6ddcSMark Murray {
15881cb6ddcSMark Murray 	return(fb64_start(&fb[CFB], dir, server));
15981cb6ddcSMark Murray }
1608fa113e5SMark Murray 
16181cb6ddcSMark Murray int
ofb64_start(int dir,int server)1628fa113e5SMark Murray ofb64_start(int dir, int server)
16381cb6ddcSMark Murray {
16481cb6ddcSMark Murray 	return(fb64_start(&fb[OFB], dir, server));
16581cb6ddcSMark Murray }
16681cb6ddcSMark Murray 
16781cb6ddcSMark Murray static int
fb64_start(struct fb * fbp,int dir,int server __unused)1688fa113e5SMark Murray fb64_start(struct fb *fbp, int dir, int server __unused)
16981cb6ddcSMark Murray {
1708fa113e5SMark Murray 	size_t x;
17181cb6ddcSMark Murray 	unsigned char *p;
1728fa113e5SMark Murray 	int state;
17381cb6ddcSMark Murray 
17481cb6ddcSMark Murray 	switch (dir) {
17581cb6ddcSMark Murray 	case DIR_DECRYPT:
17681cb6ddcSMark Murray 		/*
17781cb6ddcSMark Murray 		 * This is simply a request to have the other side
17881cb6ddcSMark Murray 		 * start output (our input).  He will negotiate an
17981cb6ddcSMark Murray 		 * IV so we need not look for it.
18081cb6ddcSMark Murray 		 */
18181cb6ddcSMark Murray 		state = fbp->state[dir-1];
18281cb6ddcSMark Murray 		if (state == FAILED)
18381cb6ddcSMark Murray 			state = IN_PROGRESS;
18481cb6ddcSMark Murray 		break;
18581cb6ddcSMark Murray 
18681cb6ddcSMark Murray 	case DIR_ENCRYPT:
18781cb6ddcSMark Murray 		state = fbp->state[dir-1];
18881cb6ddcSMark Murray 		if (state == FAILED)
18981cb6ddcSMark Murray 			state = IN_PROGRESS;
19081cb6ddcSMark Murray 		else if ((state & NO_SEND_IV) == 0)
19181cb6ddcSMark Murray 			break;
19281cb6ddcSMark Murray 
19381cb6ddcSMark Murray 		if (!VALIDKEY(fbp->krbdes_key)) {
19481cb6ddcSMark Murray 			fbp->need_start = 1;
19581cb6ddcSMark Murray 			break;
19681cb6ddcSMark Murray 		}
19781cb6ddcSMark Murray 		state &= ~NO_SEND_IV;
19881cb6ddcSMark Murray 		state |= NO_RECV_IV;
19981cb6ddcSMark Murray 		if (encrypt_debug_mode)
20081cb6ddcSMark Murray 			printf("Creating new feed\r\n");
20181cb6ddcSMark Murray 		/*
20281cb6ddcSMark Murray 		 * Create a random feed and send it over.
20381cb6ddcSMark Murray 		 */
204b285c5dfSJung-uk Kim 		DES_random_key((Block *)fbp->temp_feed);
205b285c5dfSJung-uk Kim 		DES_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed,
206b285c5dfSJung-uk Kim 				&fbp->krbdes_sched, 1);
20781cb6ddcSMark Murray 		p = fbp->fb_feed + 3;
20881cb6ddcSMark Murray 		*p++ = ENCRYPT_IS;
20981cb6ddcSMark Murray 		p++;
21081cb6ddcSMark Murray 		*p++ = FB64_IV;
21181cb6ddcSMark Murray 		for (x = 0; x < sizeof(Block); ++x) {
21281cb6ddcSMark Murray 			if ((*p++ = fbp->temp_feed[x]) == IAC)
21381cb6ddcSMark Murray 				*p++ = IAC;
21481cb6ddcSMark Murray 		}
21581cb6ddcSMark Murray 		*p++ = IAC;
21681cb6ddcSMark Murray 		*p++ = SE;
21781cb6ddcSMark Murray 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
21881cb6ddcSMark Murray 		net_write(fbp->fb_feed, p - fbp->fb_feed);
21981cb6ddcSMark Murray 		break;
22081cb6ddcSMark Murray 	default:
22181cb6ddcSMark Murray 		return(FAILED);
22281cb6ddcSMark Murray 	}
22381cb6ddcSMark Murray 	return(fbp->state[dir-1] = state);
22481cb6ddcSMark Murray }
22581cb6ddcSMark Murray 
22681cb6ddcSMark Murray /*
22781cb6ddcSMark Murray  * Returns:
22881cb6ddcSMark Murray  *	-1: some error.  Negotiation is done, encryption not ready.
22981cb6ddcSMark Murray  *	 0: Successful, initial negotiation all done.
23081cb6ddcSMark Murray  *	 1: successful, negotiation not done yet.
23181cb6ddcSMark Murray  */
23281cb6ddcSMark Murray int
cfb64_is(unsigned char * data,int cnt)2338fa113e5SMark Murray cfb64_is(unsigned char *data, int cnt)
23481cb6ddcSMark Murray {
23581cb6ddcSMark Murray 	return(fb64_is(data, cnt, &fb[CFB]));
23681cb6ddcSMark Murray }
2378fa113e5SMark Murray 
23881cb6ddcSMark Murray int
ofb64_is(unsigned char * data,int cnt)2398fa113e5SMark Murray ofb64_is(unsigned char *data, int cnt)
24081cb6ddcSMark Murray {
24181cb6ddcSMark Murray 	return(fb64_is(data, cnt, &fb[OFB]));
24281cb6ddcSMark Murray }
24381cb6ddcSMark Murray 
24481cb6ddcSMark Murray int
fb64_is(unsigned char * data,int cnt,struct fb * fbp)2458fa113e5SMark Murray fb64_is(unsigned char *data, int cnt, struct fb *fbp)
24681cb6ddcSMark Murray {
24781cb6ddcSMark Murray 	unsigned char *p;
2488fa113e5SMark Murray 	int state = fbp->state[DIR_DECRYPT-1];
24981cb6ddcSMark Murray 
25081cb6ddcSMark Murray 	if (cnt-- < 1)
25181cb6ddcSMark Murray 		goto failure;
25281cb6ddcSMark Murray 
25381cb6ddcSMark Murray 	switch (*data++) {
25481cb6ddcSMark Murray 	case FB64_IV:
25581cb6ddcSMark Murray 		if (cnt != sizeof(Block)) {
25681cb6ddcSMark Murray 			if (encrypt_debug_mode)
25781cb6ddcSMark Murray 				printf("CFB64: initial vector failed on size\r\n");
25881cb6ddcSMark Murray 			state = FAILED;
25981cb6ddcSMark Murray 			goto failure;
26081cb6ddcSMark Murray 		}
26181cb6ddcSMark Murray 
26281cb6ddcSMark Murray 		if (encrypt_debug_mode)
26381cb6ddcSMark Murray 			printf("CFB64: initial vector received\r\n");
26481cb6ddcSMark Murray 
26581cb6ddcSMark Murray 		if (encrypt_debug_mode)
26681cb6ddcSMark Murray 			printf("Initializing Decrypt stream\r\n");
26781cb6ddcSMark Murray 
26881cb6ddcSMark Murray 		fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
26981cb6ddcSMark Murray 
27081cb6ddcSMark Murray 		p = fbp->fb_feed + 3;
27181cb6ddcSMark Murray 		*p++ = ENCRYPT_REPLY;
27281cb6ddcSMark Murray 		p++;
27381cb6ddcSMark Murray 		*p++ = FB64_IV_OK;
27481cb6ddcSMark Murray 		*p++ = IAC;
27581cb6ddcSMark Murray 		*p++ = SE;
27681cb6ddcSMark Murray 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
27781cb6ddcSMark Murray 		net_write(fbp->fb_feed, p - fbp->fb_feed);
27881cb6ddcSMark Murray 
27981cb6ddcSMark Murray 		state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
28081cb6ddcSMark Murray 		break;
28181cb6ddcSMark Murray 
28281cb6ddcSMark Murray 	default:
28381cb6ddcSMark Murray 		if (encrypt_debug_mode) {
28481cb6ddcSMark Murray 			printf("Unknown option type: %d\r\n", *(data-1));
28581cb6ddcSMark Murray 			printd(data, cnt);
28681cb6ddcSMark Murray 			printf("\r\n");
28781cb6ddcSMark Murray 		}
28881cb6ddcSMark Murray 		/* FALL THROUGH */
28981cb6ddcSMark Murray 	failure:
29081cb6ddcSMark Murray 		/*
29181cb6ddcSMark Murray 		 * We failed.  Send an FB64_IV_BAD option
29281cb6ddcSMark Murray 		 * to the other side so it will know that
29381cb6ddcSMark Murray 		 * things failed.
29481cb6ddcSMark Murray 		 */
29581cb6ddcSMark Murray 		p = fbp->fb_feed + 3;
29681cb6ddcSMark Murray 		*p++ = ENCRYPT_REPLY;
29781cb6ddcSMark Murray 		p++;
29881cb6ddcSMark Murray 		*p++ = FB64_IV_BAD;
29981cb6ddcSMark Murray 		*p++ = IAC;
30081cb6ddcSMark Murray 		*p++ = SE;
30181cb6ddcSMark Murray 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
30281cb6ddcSMark Murray 		net_write(fbp->fb_feed, p - fbp->fb_feed);
30381cb6ddcSMark Murray 
30481cb6ddcSMark Murray 		break;
30581cb6ddcSMark Murray 	}
30681cb6ddcSMark Murray 	return(fbp->state[DIR_DECRYPT-1] = state);
30781cb6ddcSMark Murray }
30881cb6ddcSMark Murray 
30981cb6ddcSMark Murray /*
31081cb6ddcSMark Murray  * Returns:
31181cb6ddcSMark Murray  *	-1: some error.  Negotiation is done, encryption not ready.
31281cb6ddcSMark Murray  *	 0: Successful, initial negotiation all done.
31381cb6ddcSMark Murray  *	 1: successful, negotiation not done yet.
31481cb6ddcSMark Murray  */
31581cb6ddcSMark Murray int
cfb64_reply(unsigned char * data,int cnt)3168fa113e5SMark Murray cfb64_reply(unsigned char *data, int cnt)
31781cb6ddcSMark Murray {
31881cb6ddcSMark Murray 	return(fb64_reply(data, cnt, &fb[CFB]));
31981cb6ddcSMark Murray }
3208fa113e5SMark Murray 
32181cb6ddcSMark Murray int
ofb64_reply(unsigned char * data,int cnt)3228fa113e5SMark Murray ofb64_reply(unsigned char *data, int cnt)
32381cb6ddcSMark Murray {
32481cb6ddcSMark Murray 	return(fb64_reply(data, cnt, &fb[OFB]));
32581cb6ddcSMark Murray }
32681cb6ddcSMark Murray 
32781cb6ddcSMark Murray int
fb64_reply(unsigned char * data,int cnt,struct fb * fbp)3288fa113e5SMark Murray fb64_reply(unsigned char *data, int cnt, struct fb *fbp)
32981cb6ddcSMark Murray {
3308fa113e5SMark Murray 	int state = fbp->state[DIR_ENCRYPT-1];
33181cb6ddcSMark Murray 
33281cb6ddcSMark Murray 	if (cnt-- < 1)
33381cb6ddcSMark Murray 		goto failure;
33481cb6ddcSMark Murray 
33581cb6ddcSMark Murray 	switch (*data++) {
33681cb6ddcSMark Murray 	case FB64_IV_OK:
33781cb6ddcSMark Murray 		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
33881cb6ddcSMark Murray 		if (state == FAILED)
33981cb6ddcSMark Murray 			state = IN_PROGRESS;
34081cb6ddcSMark Murray 		state &= ~NO_RECV_IV;
3418fa113e5SMark Murray 		encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1);
34281cb6ddcSMark Murray 		break;
34381cb6ddcSMark Murray 
34481cb6ddcSMark Murray 	case FB64_IV_BAD:
34581cb6ddcSMark Murray 		memset(fbp->temp_feed, 0, sizeof(Block));
34681cb6ddcSMark Murray 		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
34781cb6ddcSMark Murray 		state = FAILED;
34881cb6ddcSMark Murray 		break;
34981cb6ddcSMark Murray 
35081cb6ddcSMark Murray 	default:
35181cb6ddcSMark Murray 		if (encrypt_debug_mode) {
35281cb6ddcSMark Murray 			printf("Unknown option type: %d\r\n", data[-1]);
35381cb6ddcSMark Murray 			printd(data, cnt);
35481cb6ddcSMark Murray 			printf("\r\n");
35581cb6ddcSMark Murray 		}
35681cb6ddcSMark Murray 		/* FALL THROUGH */
35781cb6ddcSMark Murray 	failure:
35881cb6ddcSMark Murray 		state = FAILED;
35981cb6ddcSMark Murray 		break;
36081cb6ddcSMark Murray 	}
36181cb6ddcSMark Murray 	return(fbp->state[DIR_ENCRYPT-1] = state);
36281cb6ddcSMark Murray }
36381cb6ddcSMark Murray 
36481cb6ddcSMark Murray void
cfb64_session(Session_Key * key,int server)3658fa113e5SMark Murray cfb64_session(Session_Key *key, int server)
36681cb6ddcSMark Murray {
36781cb6ddcSMark Murray 	fb64_session(key, server, &fb[CFB]);
36881cb6ddcSMark Murray }
36981cb6ddcSMark Murray 
37081cb6ddcSMark Murray void
ofb64_session(Session_Key * key,int server)3718fa113e5SMark Murray ofb64_session(Session_Key *key, int server)
37281cb6ddcSMark Murray {
37381cb6ddcSMark Murray 	fb64_session(key, server, &fb[OFB]);
37481cb6ddcSMark Murray }
37581cb6ddcSMark Murray 
37681cb6ddcSMark Murray static void
fb64_session(Session_Key * key,int server,struct fb * fbp)3778fa113e5SMark Murray fb64_session(Session_Key *key, int server, struct fb *fbp)
37881cb6ddcSMark Murray {
37981cb6ddcSMark Murray 	if (!key || key->type != SK_DES) {
38081cb6ddcSMark Murray 		if (encrypt_debug_mode)
38181cb6ddcSMark Murray 			printf("Can't set krbdes's session key (%d != %d)\r\n",
38281cb6ddcSMark Murray 				key ? key->type : -1, SK_DES);
38381cb6ddcSMark Murray 		return;
38481cb6ddcSMark Murray 	}
38581cb6ddcSMark Murray 	memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
38681cb6ddcSMark Murray 
38781cb6ddcSMark Murray 	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
38881cb6ddcSMark Murray 	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
38981cb6ddcSMark Murray 
390b285c5dfSJung-uk Kim 	DES_key_sched((Block *)fbp->krbdes_key, &fbp->krbdes_sched);
39181cb6ddcSMark Murray 	/*
39281cb6ddcSMark Murray 	 * Now look to see if krbdes_start() was was waiting for
39381cb6ddcSMark Murray 	 * the key to show up.  If so, go ahead an call it now
39481cb6ddcSMark Murray 	 * that we have the key.
39581cb6ddcSMark Murray 	 */
39681cb6ddcSMark Murray 	if (fbp->need_start) {
39781cb6ddcSMark Murray 		fbp->need_start = 0;
39881cb6ddcSMark Murray 		fb64_start(fbp, DIR_ENCRYPT, server);
39981cb6ddcSMark Murray 	}
40081cb6ddcSMark Murray }
40181cb6ddcSMark Murray 
40281cb6ddcSMark Murray /*
40381cb6ddcSMark Murray  * We only accept a keyid of 0.  If we get a keyid of
40481cb6ddcSMark Murray  * 0, then mark the state as SUCCESS.
40581cb6ddcSMark Murray  */
40681cb6ddcSMark Murray int
cfb64_keyid(int dir,unsigned char * kp,int * lenp)4078fa113e5SMark Murray cfb64_keyid(int dir, unsigned char *kp, int *lenp)
40881cb6ddcSMark Murray {
40981cb6ddcSMark Murray 	return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
41081cb6ddcSMark Murray }
41181cb6ddcSMark Murray 
41281cb6ddcSMark Murray int
ofb64_keyid(int dir,unsigned char * kp,int * lenp)4138fa113e5SMark Murray ofb64_keyid(int dir, unsigned char *kp, int *lenp)
41481cb6ddcSMark Murray {
41581cb6ddcSMark Murray 	return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
41681cb6ddcSMark Murray }
41781cb6ddcSMark Murray 
41881cb6ddcSMark Murray int
fb64_keyid(int dir,unsigned char * kp,int * lenp,struct fb * fbp)4198fa113e5SMark Murray fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp)
42081cb6ddcSMark Murray {
4218fa113e5SMark Murray 	int state = fbp->state[dir-1];
42281cb6ddcSMark Murray 
42381cb6ddcSMark Murray 	if (*lenp != 1 || (*kp != '\0')) {
42481cb6ddcSMark Murray 		*lenp = 0;
42581cb6ddcSMark Murray 		return(state);
42681cb6ddcSMark Murray 	}
42781cb6ddcSMark Murray 
42881cb6ddcSMark Murray 	if (state == FAILED)
42981cb6ddcSMark Murray 		state = IN_PROGRESS;
43081cb6ddcSMark Murray 
43181cb6ddcSMark Murray 	state &= ~NO_KEYID;
43281cb6ddcSMark Murray 
43381cb6ddcSMark Murray 	return(fbp->state[dir-1] = state);
43481cb6ddcSMark Murray }
43581cb6ddcSMark Murray 
43681cb6ddcSMark Murray void
fb64_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen,const char * type)4378fa113e5SMark Murray fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type)
43881cb6ddcSMark Murray {
43981cb6ddcSMark Murray 	char lbuf[32];
4408fa113e5SMark Murray 	int i;
44181cb6ddcSMark Murray 	char *cp;
44281cb6ddcSMark Murray 
44381cb6ddcSMark Murray 	buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
44481cb6ddcSMark Murray 	buflen -= 1;
44581cb6ddcSMark Murray 
44681cb6ddcSMark Murray 	switch(data[2]) {
44781cb6ddcSMark Murray 	case FB64_IV:
44881cb6ddcSMark Murray 		sprintf(lbuf, "%s_IV", type);
44981cb6ddcSMark Murray 		cp = lbuf;
45081cb6ddcSMark Murray 		goto common;
45181cb6ddcSMark Murray 
45281cb6ddcSMark Murray 	case FB64_IV_OK:
45381cb6ddcSMark Murray 		sprintf(lbuf, "%s_IV_OK", type);
45481cb6ddcSMark Murray 		cp = lbuf;
45581cb6ddcSMark Murray 		goto common;
45681cb6ddcSMark Murray 
45781cb6ddcSMark Murray 	case FB64_IV_BAD:
45881cb6ddcSMark Murray 		sprintf(lbuf, "%s_IV_BAD", type);
45981cb6ddcSMark Murray 		cp = lbuf;
46081cb6ddcSMark Murray 		goto common;
46181cb6ddcSMark Murray 
46281cb6ddcSMark Murray 	default:
46381cb6ddcSMark Murray 		sprintf(lbuf, " %d (unknown)", data[2]);
46481cb6ddcSMark Murray 		cp = lbuf;
46581cb6ddcSMark Murray 	common:
46681cb6ddcSMark Murray 		for (; (buflen > 0) && (*buf = *cp++); buf++)
46781cb6ddcSMark Murray 			buflen--;
46881cb6ddcSMark Murray 		for (i = 3; i < cnt; i++) {
46981cb6ddcSMark Murray 			sprintf(lbuf, " %d", data[i]);
47081cb6ddcSMark Murray 			for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
47181cb6ddcSMark Murray 				buflen--;
47281cb6ddcSMark Murray 		}
47381cb6ddcSMark Murray 		break;
47481cb6ddcSMark Murray 	}
47581cb6ddcSMark Murray }
47681cb6ddcSMark Murray 
47781cb6ddcSMark Murray void
cfb64_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)4788fa113e5SMark Murray cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
47981cb6ddcSMark Murray {
48081cb6ddcSMark Murray 	fb64_printsub(data, cnt, buf, buflen, "CFB64");
48181cb6ddcSMark Murray }
48281cb6ddcSMark Murray 
48381cb6ddcSMark Murray void
ofb64_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)4848fa113e5SMark Murray ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
48581cb6ddcSMark Murray {
48681cb6ddcSMark Murray 	fb64_printsub(data, cnt, buf, buflen, "OFB64");
48781cb6ddcSMark Murray }
48881cb6ddcSMark Murray 
48981cb6ddcSMark Murray void
fb64_stream_iv(Block seed,struct stinfo * stp)4908fa113e5SMark Murray fb64_stream_iv(Block seed, struct stinfo *stp)
49181cb6ddcSMark Murray {
49281cb6ddcSMark Murray 
49381cb6ddcSMark Murray 	memmove((void *)stp->str_iv, (void *)seed, sizeof(Block));
49481cb6ddcSMark Murray 	memmove((void *)stp->str_output, (void *)seed, sizeof(Block));
49581cb6ddcSMark Murray 
496b285c5dfSJung-uk Kim 	DES_key_sched((Block *)stp->str_ikey, &stp->str_sched);
49781cb6ddcSMark Murray 
49881cb6ddcSMark Murray 	stp->str_index = sizeof(Block);
49981cb6ddcSMark Murray }
50081cb6ddcSMark Murray 
50181cb6ddcSMark Murray void
fb64_stream_key(Block key,struct stinfo * stp)5028fa113e5SMark Murray fb64_stream_key(Block key, struct stinfo *stp)
50381cb6ddcSMark Murray {
50481cb6ddcSMark Murray 	memmove((void *)stp->str_ikey, (void *)key, sizeof(Block));
505b285c5dfSJung-uk Kim 	DES_key_sched((Block *)key, &stp->str_sched);
50681cb6ddcSMark Murray 
50781cb6ddcSMark Murray 	memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
50881cb6ddcSMark Murray 
50981cb6ddcSMark Murray 	stp->str_index = sizeof(Block);
51081cb6ddcSMark Murray }
51181cb6ddcSMark Murray 
51281cb6ddcSMark Murray /*
51381cb6ddcSMark Murray  * DES 64 bit Cipher Feedback
51481cb6ddcSMark Murray  *
51581cb6ddcSMark Murray  *     key --->+-----+
51681cb6ddcSMark Murray  *          +->| DES |--+
51781cb6ddcSMark Murray  *          |  +-----+  |
51881cb6ddcSMark Murray  *	    |           v
51981cb6ddcSMark Murray  *  INPUT --(--------->(+)+---> DATA
52081cb6ddcSMark Murray  *          |             |
52181cb6ddcSMark Murray  *	    +-------------+
52281cb6ddcSMark Murray  *
52381cb6ddcSMark Murray  *
52481cb6ddcSMark Murray  * Given:
52581cb6ddcSMark Murray  *	iV: Initial vector, 64 bits (8 bytes) long.
52681cb6ddcSMark Murray  *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
52781cb6ddcSMark Murray  *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
52881cb6ddcSMark Murray  *
52981cb6ddcSMark Murray  *	V0 = DES(iV, key)
53081cb6ddcSMark Murray  *	On = Dn ^ Vn
53181cb6ddcSMark Murray  *	V(n+1) = DES(On, key)
53281cb6ddcSMark Murray  */
53381cb6ddcSMark Murray 
53481cb6ddcSMark Murray void
cfb64_encrypt(unsigned char * s,int c)5358fa113e5SMark Murray cfb64_encrypt(unsigned char *s, int c)
53681cb6ddcSMark Murray {
5378fa113e5SMark Murray 	struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
5388fa113e5SMark Murray 	int idx;
53981cb6ddcSMark Murray 
5408fa113e5SMark Murray 	idx = stp->str_index;
54181cb6ddcSMark Murray 	while (c-- > 0) {
5428fa113e5SMark Murray 		if (idx == sizeof(Block)) {
54381cb6ddcSMark Murray 			Block b;
544b285c5dfSJung-uk Kim 			DES_ecb_encrypt((Block *)stp->str_output, (Block *)b, &stp->str_sched, 1);
54581cb6ddcSMark Murray 			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
5468fa113e5SMark Murray 			idx = 0;
54781cb6ddcSMark Murray 		}
54881cb6ddcSMark Murray 
54981cb6ddcSMark Murray 		/* On encryption, we store (feed ^ data) which is cypher */
5508fa113e5SMark Murray 		*s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s);
55181cb6ddcSMark Murray 		s++;
5528fa113e5SMark Murray 		idx++;
55381cb6ddcSMark Murray 	}
5548fa113e5SMark Murray 	stp->str_index = idx;
55581cb6ddcSMark Murray }
55681cb6ddcSMark Murray 
55781cb6ddcSMark Murray int
cfb64_decrypt(int data)5588fa113e5SMark Murray cfb64_decrypt(int data)
55981cb6ddcSMark Murray {
5608fa113e5SMark Murray 	struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
5618fa113e5SMark Murray 	int idx;
56281cb6ddcSMark Murray 
56381cb6ddcSMark Murray 	if (data == -1) {
56481cb6ddcSMark Murray 		/*
56581cb6ddcSMark Murray 		 * Back up one byte.  It is assumed that we will
56681cb6ddcSMark Murray 		 * never back up more than one byte.  If we do, this
56781cb6ddcSMark Murray 		 * may or may not work.
56881cb6ddcSMark Murray 		 */
56981cb6ddcSMark Murray 		if (stp->str_index)
57081cb6ddcSMark Murray 			--stp->str_index;
57181cb6ddcSMark Murray 		return(0);
57281cb6ddcSMark Murray 	}
57381cb6ddcSMark Murray 
5748fa113e5SMark Murray 	idx = stp->str_index++;
5758fa113e5SMark Murray 	if (idx == sizeof(Block)) {
57681cb6ddcSMark Murray 		Block b;
577b285c5dfSJung-uk Kim 		DES_ecb_encrypt((Block *)stp->str_output, (Block *)b, &stp->str_sched, 1);
57881cb6ddcSMark Murray 		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
57981cb6ddcSMark Murray 		stp->str_index = 1;	/* Next time will be 1 */
5808fa113e5SMark Murray 		idx = 0;		/* But now use 0 */
58181cb6ddcSMark Murray 	}
58281cb6ddcSMark Murray 
58381cb6ddcSMark Murray 	/* On decryption we store (data) which is cypher. */
5848fa113e5SMark Murray 	stp->str_output[idx] = data;
5858fa113e5SMark Murray 	return(data ^ stp->str_feed[idx]);
58681cb6ddcSMark Murray }
58781cb6ddcSMark Murray 
58881cb6ddcSMark Murray /*
58981cb6ddcSMark Murray  * DES 64 bit Output Feedback
59081cb6ddcSMark Murray  *
59181cb6ddcSMark Murray  * key --->+-----+
59281cb6ddcSMark Murray  *	+->| DES |--+
59381cb6ddcSMark Murray  *	|  +-----+  |
59481cb6ddcSMark Murray  *	+-----------+
59581cb6ddcSMark Murray  *	            v
59681cb6ddcSMark Murray  *  INPUT -------->(+) ----> DATA
59781cb6ddcSMark Murray  *
59881cb6ddcSMark Murray  * Given:
59981cb6ddcSMark Murray  *	iV: Initial vector, 64 bits (8 bytes) long.
60081cb6ddcSMark Murray  *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
60181cb6ddcSMark Murray  *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
60281cb6ddcSMark Murray  *
60381cb6ddcSMark Murray  *	V0 = DES(iV, key)
60481cb6ddcSMark Murray  *	V(n+1) = DES(Vn, key)
60581cb6ddcSMark Murray  *	On = Dn ^ Vn
60681cb6ddcSMark Murray  */
60781cb6ddcSMark Murray void
ofb64_encrypt(unsigned char * s,int c)6088fa113e5SMark Murray ofb64_encrypt(unsigned char *s, int c)
60981cb6ddcSMark Murray {
6108fa113e5SMark Murray 	struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
6118fa113e5SMark Murray 	int idx;
61281cb6ddcSMark Murray 
6138fa113e5SMark Murray 	idx = stp->str_index;
61481cb6ddcSMark Murray 	while (c-- > 0) {
6158fa113e5SMark Murray 		if (idx == sizeof(Block)) {
61681cb6ddcSMark Murray 			Block b;
617b285c5dfSJung-uk Kim 			DES_ecb_encrypt((Block *)stp->str_feed, (Block *)b, &stp->str_sched, 1);
61881cb6ddcSMark Murray 			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
6198fa113e5SMark Murray 			idx = 0;
62081cb6ddcSMark Murray 		}
6218fa113e5SMark Murray 		*s++ ^= stp->str_feed[idx];
6228fa113e5SMark Murray 		idx++;
62381cb6ddcSMark Murray 	}
6248fa113e5SMark Murray 	stp->str_index = idx;
62581cb6ddcSMark Murray }
62681cb6ddcSMark Murray 
62781cb6ddcSMark Murray int
ofb64_decrypt(int data)6288fa113e5SMark Murray ofb64_decrypt(int data)
62981cb6ddcSMark Murray {
6308fa113e5SMark Murray 	struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
6318fa113e5SMark Murray 	int idx;
63281cb6ddcSMark Murray 
63381cb6ddcSMark Murray 	if (data == -1) {
63481cb6ddcSMark Murray 		/*
63581cb6ddcSMark Murray 		 * Back up one byte.  It is assumed that we will
63681cb6ddcSMark Murray 		 * never back up more than one byte.  If we do, this
63781cb6ddcSMark Murray 		 * may or may not work.
63881cb6ddcSMark Murray 		 */
63981cb6ddcSMark Murray 		if (stp->str_index)
64081cb6ddcSMark Murray 			--stp->str_index;
64181cb6ddcSMark Murray 		return(0);
64281cb6ddcSMark Murray 	}
64381cb6ddcSMark Murray 
6448fa113e5SMark Murray 	idx = stp->str_index++;
6458fa113e5SMark Murray 	if (idx == sizeof(Block)) {
64681cb6ddcSMark Murray 		Block b;
647b285c5dfSJung-uk Kim 		DES_ecb_encrypt((Block *)stp->str_feed, (Block *)b, &stp->str_sched, 1);
64881cb6ddcSMark Murray 		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
64981cb6ddcSMark Murray 		stp->str_index = 1;	/* Next time will be 1 */
6508fa113e5SMark Murray 		idx = 0;		/* But now use 0 */
65181cb6ddcSMark Murray 	}
65281cb6ddcSMark Murray 
6538fa113e5SMark Murray 	return(data ^ stp->str_feed[idx]);
65481cb6ddcSMark Murray }
65581cb6ddcSMark Murray # endif	/* AUTHENTICATION */
65681cb6ddcSMark Murray #endif	/* ENCRYPTION */
657