xref: /dflybsd-src/lib/libtelnet/enc_des.c (revision 82ae7067fc7cf43ff19ea78e572c205e1875d28e)
1068e7061SPeter Avalos /*-
2068e7061SPeter Avalos  * Copyright (c) 1991, 1993
3068e7061SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
4068e7061SPeter Avalos  *
5068e7061SPeter Avalos  * Redistribution and use in source and binary forms, with or without
6068e7061SPeter Avalos  * modification, are permitted provided that the following conditions
7068e7061SPeter Avalos  * are met:
8068e7061SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
9068e7061SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
10068e7061SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
11068e7061SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
12068e7061SPeter Avalos  *    documentation and/or other materials provided with the distribution.
13dc71b7abSJustin C. Sherrill  * 3. Neither the name of the University nor the names of its contributors
14068e7061SPeter Avalos  *    may be used to endorse or promote products derived from this software
15068e7061SPeter Avalos  *    without specific prior written permission.
16068e7061SPeter Avalos  *
17068e7061SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18068e7061SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19068e7061SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20068e7061SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21068e7061SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22068e7061SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23068e7061SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24068e7061SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25068e7061SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26068e7061SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27068e7061SPeter Avalos  * SUCH DAMAGE.
28068e7061SPeter Avalos  *
29068e7061SPeter Avalos  * $FreeBSD: src/crypto/telnet/libtelnet/enc_des.c,v 1.3.2.2 2003/02/14 22:38:13 nectar Exp $
30068e7061SPeter Avalos  * $DragonFly: src/crypto/telnet/libtelnet/enc_des.c,v 1.2 2003/06/17 04:24:37 dillon Exp $
31068e7061SPeter Avalos  *
32068e7061SPeter Avalos  * @(#)enc_des.c	8.3 (Berkeley) 5/30/95
33068e7061SPeter Avalos  * $FreeBSD: src/crypto/telnet/libtelnet/enc_des.c,v 1.3.2.2 2003/02/14 22:38:13 nectar Exp $
34068e7061SPeter Avalos  */
35068e7061SPeter Avalos 
36068e7061SPeter Avalos #ifdef	ENCRYPTION
37068e7061SPeter Avalos # ifdef	AUTHENTICATION
38068e7061SPeter Avalos #include <arpa/telnet.h>
39068e7061SPeter Avalos #include <openssl/des.h>
40068e7061SPeter Avalos #include <stdio.h>
41068e7061SPeter Avalos #include <stdlib.h>
42068e7061SPeter Avalos #include <string.h>
43068e7061SPeter Avalos 
44068e7061SPeter Avalos #include "encrypt.h"
45068e7061SPeter Avalos #include "key-proto.h"
46068e7061SPeter Avalos #include "misc-proto.h"
47068e7061SPeter Avalos 
48068e7061SPeter Avalos extern int encrypt_debug_mode;
49068e7061SPeter Avalos 
50068e7061SPeter Avalos #define	CFB	0
51068e7061SPeter Avalos #define	OFB	1
52068e7061SPeter Avalos 
53068e7061SPeter Avalos #define	NO_SEND_IV	1
54068e7061SPeter Avalos #define	NO_RECV_IV	2
55068e7061SPeter Avalos #define	NO_KEYID	4
56068e7061SPeter Avalos #define	IN_PROGRESS	(NO_SEND_IV|NO_RECV_IV|NO_KEYID)
57068e7061SPeter Avalos #define	SUCCESS		0
58068e7061SPeter Avalos #define	FAILED		-1
59068e7061SPeter Avalos 
60068e7061SPeter Avalos 
61068e7061SPeter Avalos struct fb {
62068e7061SPeter Avalos 	Block krbdes_key;
63068e7061SPeter Avalos 	Schedule krbdes_sched;
64068e7061SPeter Avalos 	Block temp_feed;
65068e7061SPeter Avalos 	unsigned char fb_feed[64];
66068e7061SPeter Avalos 	int need_start;
67068e7061SPeter Avalos 	int state[2];
68068e7061SPeter Avalos 	int keyid[2];
69068e7061SPeter Avalos 	struct stinfo {
70068e7061SPeter Avalos 		Block		str_output;
71068e7061SPeter Avalos 		Block		str_feed;
72068e7061SPeter Avalos 		Block		str_iv;
73068e7061SPeter Avalos 		Block		str_ikey;
74068e7061SPeter Avalos 		Schedule	str_sched;
75068e7061SPeter Avalos 		int		str_index;
76068e7061SPeter Avalos 		int		str_flagshift;
77068e7061SPeter Avalos 	} streams[2];
78068e7061SPeter Avalos };
79068e7061SPeter Avalos 
80068e7061SPeter Avalos static struct fb fb[2];
81068e7061SPeter Avalos 
82068e7061SPeter Avalos struct keyidlist {
83068e7061SPeter Avalos 	const char *keyid;
84068e7061SPeter Avalos 	int	keyidlen;
85068e7061SPeter Avalos 	char	*key;
86068e7061SPeter Avalos 	int	keylen;
87068e7061SPeter Avalos 	int	flags;
88068e7061SPeter Avalos } keyidlist [] = {
89068e7061SPeter Avalos 	{ "\0", 1, 0, 0, 0 },		/* default key of zero */
90068e7061SPeter Avalos 	{ 0, 0, 0, 0, 0 }
91068e7061SPeter Avalos };
92068e7061SPeter Avalos 
93068e7061SPeter Avalos #define	KEYFLAG_MASK	03
94068e7061SPeter Avalos 
95068e7061SPeter Avalos #define	KEYFLAG_NOINIT	00
96068e7061SPeter Avalos #define	KEYFLAG_INIT	01
97068e7061SPeter Avalos #define	KEYFLAG_OK	02
98068e7061SPeter Avalos #define	KEYFLAG_BAD	03
99068e7061SPeter Avalos 
100068e7061SPeter Avalos #define	KEYFLAG_SHIFT	2
101068e7061SPeter Avalos 
102068e7061SPeter Avalos #define	SHIFT_VAL(a,b)	(KEYFLAG_SHIFT*((a)+((b)*2)))
103068e7061SPeter Avalos 
104068e7061SPeter Avalos #define	FB64_IV		1
105068e7061SPeter Avalos #define	FB64_IV_OK	2
106068e7061SPeter Avalos #define	FB64_IV_BAD	3
107068e7061SPeter Avalos 
108068e7061SPeter Avalos 
109068e7061SPeter Avalos void fb64_stream_iv(Block, struct stinfo *);
110068e7061SPeter Avalos void fb64_init(struct fb *);
111068e7061SPeter Avalos static int fb64_start(struct fb *, int, int);
112068e7061SPeter Avalos int fb64_is(unsigned char *, int, struct fb *);
113068e7061SPeter Avalos int fb64_reply(unsigned char *, int, struct fb *);
114068e7061SPeter Avalos static void fb64_session(Session_Key *, int, struct fb *);
115068e7061SPeter Avalos void fb64_stream_key(Block, struct stinfo *);
116068e7061SPeter Avalos int fb64_keyid(int, unsigned char *, int *, struct fb *);
117068e7061SPeter Avalos 
118068e7061SPeter Avalos void
cfb64_init(int server __unused)119068e7061SPeter Avalos cfb64_init(int server __unused)
120068e7061SPeter Avalos {
121068e7061SPeter Avalos 	fb64_init(&fb[CFB]);
122068e7061SPeter Avalos 	fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
123068e7061SPeter Avalos 	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
124068e7061SPeter Avalos 	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
125068e7061SPeter Avalos }
126068e7061SPeter Avalos 
127068e7061SPeter Avalos void
ofb64_init(int server __unused)128068e7061SPeter Avalos ofb64_init(int server __unused)
129068e7061SPeter Avalos {
130068e7061SPeter Avalos 	fb64_init(&fb[OFB]);
131068e7061SPeter Avalos 	fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
132068e7061SPeter Avalos 	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
133068e7061SPeter Avalos 	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
134068e7061SPeter Avalos }
135068e7061SPeter Avalos 
136068e7061SPeter Avalos void
fb64_init(struct fb * fbp)137068e7061SPeter Avalos fb64_init(struct fb *fbp)
138068e7061SPeter Avalos {
139068e7061SPeter Avalos 	memset((void *)fbp, 0, sizeof(*fbp));
140068e7061SPeter Avalos 	fbp->state[0] = fbp->state[1] = FAILED;
141068e7061SPeter Avalos 	fbp->fb_feed[0] = IAC;
142068e7061SPeter Avalos 	fbp->fb_feed[1] = SB;
143068e7061SPeter Avalos 	fbp->fb_feed[2] = TELOPT_ENCRYPT;
144068e7061SPeter Avalos 	fbp->fb_feed[3] = ENCRYPT_IS;
145068e7061SPeter Avalos }
146068e7061SPeter Avalos 
147068e7061SPeter Avalos /*
148068e7061SPeter Avalos  * Returns:
149068e7061SPeter Avalos  *	-1: some error.  Negotiation is done, encryption not ready.
150068e7061SPeter Avalos  *	 0: Successful, initial negotiation all done.
151068e7061SPeter Avalos  *	 1: successful, negotiation not done yet.
152068e7061SPeter Avalos  *	 2: Not yet.  Other things (like getting the key from
153068e7061SPeter Avalos  *	    Kerberos) have to happen before we can continue.
154068e7061SPeter Avalos  */
155068e7061SPeter Avalos int
cfb64_start(int dir,int server)156068e7061SPeter Avalos cfb64_start(int dir, int server)
157068e7061SPeter Avalos {
158068e7061SPeter Avalos 	return(fb64_start(&fb[CFB], dir, server));
159068e7061SPeter Avalos }
160068e7061SPeter Avalos 
161068e7061SPeter Avalos int
ofb64_start(int dir,int server)162068e7061SPeter Avalos ofb64_start(int dir, int server)
163068e7061SPeter Avalos {
164068e7061SPeter Avalos 	return(fb64_start(&fb[OFB], dir, server));
165068e7061SPeter Avalos }
166068e7061SPeter Avalos 
167068e7061SPeter Avalos static int
fb64_start(struct fb * fbp,int dir,int server __unused)168068e7061SPeter Avalos fb64_start(struct fb *fbp, int dir, int server __unused)
169068e7061SPeter Avalos {
170068e7061SPeter Avalos 	size_t x;
171068e7061SPeter Avalos 	unsigned char *p;
172068e7061SPeter Avalos 	int state;
173068e7061SPeter Avalos 
174068e7061SPeter Avalos 	switch (dir) {
175068e7061SPeter Avalos 	case DIR_DECRYPT:
176068e7061SPeter Avalos 		/*
177068e7061SPeter Avalos 		 * This is simply a request to have the other side
178068e7061SPeter Avalos 		 * start output (our input).  He will negotiate an
179068e7061SPeter Avalos 		 * IV so we need not look for it.
180068e7061SPeter Avalos 		 */
181068e7061SPeter Avalos 		state = fbp->state[dir-1];
182068e7061SPeter Avalos 		if (state == FAILED)
183068e7061SPeter Avalos 			state = IN_PROGRESS;
184068e7061SPeter Avalos 		break;
185068e7061SPeter Avalos 
186068e7061SPeter Avalos 	case DIR_ENCRYPT:
187068e7061SPeter Avalos 		state = fbp->state[dir-1];
188068e7061SPeter Avalos 		if (state == FAILED)
189068e7061SPeter Avalos 			state = IN_PROGRESS;
190068e7061SPeter Avalos 		else if ((state & NO_SEND_IV) == 0)
191068e7061SPeter Avalos 			break;
192068e7061SPeter Avalos 
193068e7061SPeter Avalos 		if (!VALIDKEY(fbp->krbdes_key)) {
194068e7061SPeter Avalos 			fbp->need_start = 1;
195068e7061SPeter Avalos 			break;
196068e7061SPeter Avalos 		}
197068e7061SPeter Avalos 		state &= ~NO_SEND_IV;
198068e7061SPeter Avalos 		state |= NO_RECV_IV;
199068e7061SPeter Avalos 		if (encrypt_debug_mode)
200068e7061SPeter Avalos 			printf("Creating new feed\r\n");
201068e7061SPeter Avalos 		/*
202068e7061SPeter Avalos 		 * Create a random feed and send it over.
203068e7061SPeter Avalos 		 */
204*82ae7067SJohn Marino 		DES_random_key((Block *)fbp->temp_feed);
205*82ae7067SJohn Marino 		DES_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed,
206*82ae7067SJohn Marino 				&fbp->krbdes_sched, 1);
207068e7061SPeter Avalos 		p = fbp->fb_feed + 3;
208068e7061SPeter Avalos 		*p++ = ENCRYPT_IS;
209068e7061SPeter Avalos 		p++;
210068e7061SPeter Avalos 		*p++ = FB64_IV;
211068e7061SPeter Avalos 		for (x = 0; x < sizeof(Block); ++x) {
212068e7061SPeter Avalos 			if ((*p++ = fbp->temp_feed[x]) == IAC)
213068e7061SPeter Avalos 				*p++ = IAC;
214068e7061SPeter Avalos 		}
215068e7061SPeter Avalos 		*p++ = IAC;
216068e7061SPeter Avalos 		*p++ = SE;
217068e7061SPeter Avalos 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
218068e7061SPeter Avalos 		net_write(fbp->fb_feed, p - fbp->fb_feed);
219068e7061SPeter Avalos 		break;
220068e7061SPeter Avalos 	default:
221068e7061SPeter Avalos 		return(FAILED);
222068e7061SPeter Avalos 	}
223068e7061SPeter Avalos 	return(fbp->state[dir-1] = state);
224068e7061SPeter Avalos }
225068e7061SPeter Avalos 
226068e7061SPeter Avalos /*
227068e7061SPeter Avalos  * Returns:
228068e7061SPeter Avalos  *	-1: some error.  Negotiation is done, encryption not ready.
229068e7061SPeter Avalos  *	 0: Successful, initial negotiation all done.
230068e7061SPeter Avalos  *	 1: successful, negotiation not done yet.
231068e7061SPeter Avalos  */
232068e7061SPeter Avalos int
cfb64_is(unsigned char * data,int cnt)233068e7061SPeter Avalos cfb64_is(unsigned char *data, int cnt)
234068e7061SPeter Avalos {
235068e7061SPeter Avalos 	return(fb64_is(data, cnt, &fb[CFB]));
236068e7061SPeter Avalos }
237068e7061SPeter Avalos 
238068e7061SPeter Avalos int
ofb64_is(unsigned char * data,int cnt)239068e7061SPeter Avalos ofb64_is(unsigned char *data, int cnt)
240068e7061SPeter Avalos {
241068e7061SPeter Avalos 	return(fb64_is(data, cnt, &fb[OFB]));
242068e7061SPeter Avalos }
243068e7061SPeter Avalos 
244068e7061SPeter Avalos int
fb64_is(unsigned char * data,int cnt,struct fb * fbp)245068e7061SPeter Avalos fb64_is(unsigned char *data, int cnt, struct fb *fbp)
246068e7061SPeter Avalos {
247068e7061SPeter Avalos 	unsigned char *p;
248068e7061SPeter Avalos 	int state = fbp->state[DIR_DECRYPT-1];
249068e7061SPeter Avalos 
250068e7061SPeter Avalos 	if (cnt-- < 1)
251068e7061SPeter Avalos 		goto failure;
252068e7061SPeter Avalos 
253068e7061SPeter Avalos 	switch (*data++) {
254068e7061SPeter Avalos 	case FB64_IV:
255068e7061SPeter Avalos 		if (cnt != sizeof(Block)) {
256068e7061SPeter Avalos 			if (encrypt_debug_mode)
257068e7061SPeter Avalos 				printf("CFB64: initial vector failed on size\r\n");
258068e7061SPeter Avalos 			state = FAILED;
259068e7061SPeter Avalos 			goto failure;
260068e7061SPeter Avalos 		}
261068e7061SPeter Avalos 
262068e7061SPeter Avalos 		if (encrypt_debug_mode)
263068e7061SPeter Avalos 			printf("CFB64: initial vector received\r\n");
264068e7061SPeter Avalos 
265068e7061SPeter Avalos 		if (encrypt_debug_mode)
266068e7061SPeter Avalos 			printf("Initializing Decrypt stream\r\n");
267068e7061SPeter Avalos 
268068e7061SPeter Avalos 		fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
269068e7061SPeter Avalos 
270068e7061SPeter Avalos 		p = fbp->fb_feed + 3;
271068e7061SPeter Avalos 		*p++ = ENCRYPT_REPLY;
272068e7061SPeter Avalos 		p++;
273068e7061SPeter Avalos 		*p++ = FB64_IV_OK;
274068e7061SPeter Avalos 		*p++ = IAC;
275068e7061SPeter Avalos 		*p++ = SE;
276068e7061SPeter Avalos 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
277068e7061SPeter Avalos 		net_write(fbp->fb_feed, p - fbp->fb_feed);
278068e7061SPeter Avalos 
279068e7061SPeter Avalos 		state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
280068e7061SPeter Avalos 		break;
281068e7061SPeter Avalos 
282068e7061SPeter Avalos 	default:
283068e7061SPeter Avalos 		if (encrypt_debug_mode) {
284068e7061SPeter Avalos 			printf("Unknown option type: %d\r\n", *(data-1));
285068e7061SPeter Avalos 			printd(data, cnt);
286068e7061SPeter Avalos 			printf("\r\n");
287068e7061SPeter Avalos 		}
288068e7061SPeter Avalos 		/* FALL THROUGH */
289068e7061SPeter Avalos 	failure:
290068e7061SPeter Avalos 		/*
291068e7061SPeter Avalos 		 * We failed.  Send an FB64_IV_BAD option
292068e7061SPeter Avalos 		 * to the other side so it will know that
293068e7061SPeter Avalos 		 * things failed.
294068e7061SPeter Avalos 		 */
295068e7061SPeter Avalos 		p = fbp->fb_feed + 3;
296068e7061SPeter Avalos 		*p++ = ENCRYPT_REPLY;
297068e7061SPeter Avalos 		p++;
298068e7061SPeter Avalos 		*p++ = FB64_IV_BAD;
299068e7061SPeter Avalos 		*p++ = IAC;
300068e7061SPeter Avalos 		*p++ = SE;
301068e7061SPeter Avalos 		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
302068e7061SPeter Avalos 		net_write(fbp->fb_feed, p - fbp->fb_feed);
303068e7061SPeter Avalos 
304068e7061SPeter Avalos 		break;
305068e7061SPeter Avalos 	}
306068e7061SPeter Avalos 	return(fbp->state[DIR_DECRYPT-1] = state);
307068e7061SPeter Avalos }
308068e7061SPeter Avalos 
309068e7061SPeter Avalos /*
310068e7061SPeter Avalos  * Returns:
311068e7061SPeter Avalos  *	-1: some error.  Negotiation is done, encryption not ready.
312068e7061SPeter Avalos  *	 0: Successful, initial negotiation all done.
313068e7061SPeter Avalos  *	 1: successful, negotiation not done yet.
314068e7061SPeter Avalos  */
315068e7061SPeter Avalos int
cfb64_reply(unsigned char * data,int cnt)316068e7061SPeter Avalos cfb64_reply(unsigned char *data, int cnt)
317068e7061SPeter Avalos {
318068e7061SPeter Avalos 	return(fb64_reply(data, cnt, &fb[CFB]));
319068e7061SPeter Avalos }
320068e7061SPeter Avalos 
321068e7061SPeter Avalos int
ofb64_reply(unsigned char * data,int cnt)322068e7061SPeter Avalos ofb64_reply(unsigned char *data, int cnt)
323068e7061SPeter Avalos {
324068e7061SPeter Avalos 	return(fb64_reply(data, cnt, &fb[OFB]));
325068e7061SPeter Avalos }
326068e7061SPeter Avalos 
327068e7061SPeter Avalos int
fb64_reply(unsigned char * data,int cnt,struct fb * fbp)328068e7061SPeter Avalos fb64_reply(unsigned char *data, int cnt, struct fb *fbp)
329068e7061SPeter Avalos {
330068e7061SPeter Avalos 	int state = fbp->state[DIR_ENCRYPT-1];
331068e7061SPeter Avalos 
332068e7061SPeter Avalos 	if (cnt-- < 1)
333068e7061SPeter Avalos 		goto failure;
334068e7061SPeter Avalos 
335068e7061SPeter Avalos 	switch (*data++) {
336068e7061SPeter Avalos 	case FB64_IV_OK:
337068e7061SPeter Avalos 		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
338068e7061SPeter Avalos 		if (state == FAILED)
339068e7061SPeter Avalos 			state = IN_PROGRESS;
340068e7061SPeter Avalos 		state &= ~NO_RECV_IV;
341068e7061SPeter Avalos 		encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1);
342068e7061SPeter Avalos 		break;
343068e7061SPeter Avalos 
344068e7061SPeter Avalos 	case FB64_IV_BAD:
345068e7061SPeter Avalos 		memset(fbp->temp_feed, 0, sizeof(Block));
346068e7061SPeter Avalos 		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
347068e7061SPeter Avalos 		state = FAILED;
348068e7061SPeter Avalos 		break;
349068e7061SPeter Avalos 
350068e7061SPeter Avalos 	default:
351068e7061SPeter Avalos 		if (encrypt_debug_mode) {
352068e7061SPeter Avalos 			printf("Unknown option type: %d\r\n", data[-1]);
353068e7061SPeter Avalos 			printd(data, cnt);
354068e7061SPeter Avalos 			printf("\r\n");
355068e7061SPeter Avalos 		}
356068e7061SPeter Avalos 		/* FALL THROUGH */
357068e7061SPeter Avalos 	failure:
358068e7061SPeter Avalos 		state = FAILED;
359068e7061SPeter Avalos 		break;
360068e7061SPeter Avalos 	}
361068e7061SPeter Avalos 	return(fbp->state[DIR_ENCRYPT-1] = state);
362068e7061SPeter Avalos }
363068e7061SPeter Avalos 
364068e7061SPeter Avalos void
cfb64_session(Session_Key * key,int server)365068e7061SPeter Avalos cfb64_session(Session_Key *key, int server)
366068e7061SPeter Avalos {
367068e7061SPeter Avalos 	fb64_session(key, server, &fb[CFB]);
368068e7061SPeter Avalos }
369068e7061SPeter Avalos 
370068e7061SPeter Avalos void
ofb64_session(Session_Key * key,int server)371068e7061SPeter Avalos ofb64_session(Session_Key *key, int server)
372068e7061SPeter Avalos {
373068e7061SPeter Avalos 	fb64_session(key, server, &fb[OFB]);
374068e7061SPeter Avalos }
375068e7061SPeter Avalos 
376068e7061SPeter Avalos static void
fb64_session(Session_Key * key,int server,struct fb * fbp)377068e7061SPeter Avalos fb64_session(Session_Key *key, int server, struct fb *fbp)
378068e7061SPeter Avalos {
379068e7061SPeter Avalos 	if (!key || key->type != SK_DES) {
380068e7061SPeter Avalos 		if (encrypt_debug_mode)
381068e7061SPeter Avalos 			printf("Can't set krbdes's session key (%d != %d)\r\n",
382068e7061SPeter Avalos 				key ? key->type : -1, SK_DES);
383068e7061SPeter Avalos 		return;
384068e7061SPeter Avalos 	}
385068e7061SPeter Avalos 	memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
386068e7061SPeter Avalos 
387068e7061SPeter Avalos 	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
388068e7061SPeter Avalos 	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
389068e7061SPeter Avalos 
390*82ae7067SJohn Marino 	DES_key_sched((Block *)fbp->krbdes_key, &fbp->krbdes_sched);
391068e7061SPeter Avalos 	/*
392068e7061SPeter Avalos 	 * Now look to see if krbdes_start() was was waiting for
393068e7061SPeter Avalos 	 * the key to show up.  If so, go ahead an call it now
394068e7061SPeter Avalos 	 * that we have the key.
395068e7061SPeter Avalos 	 */
396068e7061SPeter Avalos 	if (fbp->need_start) {
397068e7061SPeter Avalos 		fbp->need_start = 0;
398068e7061SPeter Avalos 		fb64_start(fbp, DIR_ENCRYPT, server);
399068e7061SPeter Avalos 	}
400068e7061SPeter Avalos }
401068e7061SPeter Avalos 
402068e7061SPeter Avalos /*
403068e7061SPeter Avalos  * We only accept a keyid of 0.  If we get a keyid of
404068e7061SPeter Avalos  * 0, then mark the state as SUCCESS.
405068e7061SPeter Avalos  */
406068e7061SPeter Avalos int
cfb64_keyid(int dir,unsigned char * kp,int * lenp)407068e7061SPeter Avalos cfb64_keyid(int dir, unsigned char *kp, int *lenp)
408068e7061SPeter Avalos {
409068e7061SPeter Avalos 	return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
410068e7061SPeter Avalos }
411068e7061SPeter Avalos 
412068e7061SPeter Avalos int
ofb64_keyid(int dir,unsigned char * kp,int * lenp)413068e7061SPeter Avalos ofb64_keyid(int dir, unsigned char *kp, int *lenp)
414068e7061SPeter Avalos {
415068e7061SPeter Avalos 	return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
416068e7061SPeter Avalos }
417068e7061SPeter Avalos 
418068e7061SPeter Avalos int
fb64_keyid(int dir,unsigned char * kp,int * lenp,struct fb * fbp)419068e7061SPeter Avalos fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp)
420068e7061SPeter Avalos {
421068e7061SPeter Avalos 	int state = fbp->state[dir-1];
422068e7061SPeter Avalos 
423068e7061SPeter Avalos 	if (*lenp != 1 || (*kp != '\0')) {
424068e7061SPeter Avalos 		*lenp = 0;
425068e7061SPeter Avalos 		return(state);
426068e7061SPeter Avalos 	}
427068e7061SPeter Avalos 
428068e7061SPeter Avalos 	if (state == FAILED)
429068e7061SPeter Avalos 		state = IN_PROGRESS;
430068e7061SPeter Avalos 
431068e7061SPeter Avalos 	state &= ~NO_KEYID;
432068e7061SPeter Avalos 
433068e7061SPeter Avalos 	return(fbp->state[dir-1] = state);
434068e7061SPeter Avalos }
435068e7061SPeter Avalos 
436068e7061SPeter Avalos void
fb64_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen,const char * type)437068e7061SPeter Avalos fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type)
438068e7061SPeter Avalos {
439068e7061SPeter Avalos 	char lbuf[32];
440068e7061SPeter Avalos 	int i;
441068e7061SPeter Avalos 	char *cp;
442068e7061SPeter Avalos 
443068e7061SPeter Avalos 	buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
444068e7061SPeter Avalos 	buflen -= 1;
445068e7061SPeter Avalos 
446068e7061SPeter Avalos 	switch(data[2]) {
447068e7061SPeter Avalos 	case FB64_IV:
448068e7061SPeter Avalos 		sprintf(lbuf, "%s_IV", type);
449068e7061SPeter Avalos 		cp = lbuf;
450068e7061SPeter Avalos 		goto common;
451068e7061SPeter Avalos 
452068e7061SPeter Avalos 	case FB64_IV_OK:
453068e7061SPeter Avalos 		sprintf(lbuf, "%s_IV_OK", type);
454068e7061SPeter Avalos 		cp = lbuf;
455068e7061SPeter Avalos 		goto common;
456068e7061SPeter Avalos 
457068e7061SPeter Avalos 	case FB64_IV_BAD:
458068e7061SPeter Avalos 		sprintf(lbuf, "%s_IV_BAD", type);
459068e7061SPeter Avalos 		cp = lbuf;
460068e7061SPeter Avalos 		goto common;
461068e7061SPeter Avalos 
462068e7061SPeter Avalos 	default:
463068e7061SPeter Avalos 		sprintf(lbuf, " %d (unknown)", data[2]);
464068e7061SPeter Avalos 		cp = lbuf;
465068e7061SPeter Avalos 	common:
466068e7061SPeter Avalos 		for (; (buflen > 0) && (*buf = *cp++); buf++)
467068e7061SPeter Avalos 			buflen--;
468068e7061SPeter Avalos 		for (i = 3; i < cnt; i++) {
469068e7061SPeter Avalos 			sprintf(lbuf, " %d", data[i]);
470068e7061SPeter Avalos 			for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
471068e7061SPeter Avalos 				buflen--;
472068e7061SPeter Avalos 		}
473068e7061SPeter Avalos 		break;
474068e7061SPeter Avalos 	}
475068e7061SPeter Avalos }
476068e7061SPeter Avalos 
477068e7061SPeter Avalos void
cfb64_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)478068e7061SPeter Avalos cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
479068e7061SPeter Avalos {
480068e7061SPeter Avalos 	fb64_printsub(data, cnt, buf, buflen, "CFB64");
481068e7061SPeter Avalos }
482068e7061SPeter Avalos 
483068e7061SPeter Avalos void
ofb64_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)484068e7061SPeter Avalos ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
485068e7061SPeter Avalos {
486068e7061SPeter Avalos 	fb64_printsub(data, cnt, buf, buflen, "OFB64");
487068e7061SPeter Avalos }
488068e7061SPeter Avalos 
489068e7061SPeter Avalos void
fb64_stream_iv(Block seed,struct stinfo * stp)490068e7061SPeter Avalos fb64_stream_iv(Block seed, struct stinfo *stp)
491068e7061SPeter Avalos {
492068e7061SPeter Avalos 
493068e7061SPeter Avalos 	memmove((void *)stp->str_iv, (void *)seed, sizeof(Block));
494068e7061SPeter Avalos 	memmove((void *)stp->str_output, (void *)seed, sizeof(Block));
495068e7061SPeter Avalos 
496*82ae7067SJohn Marino 	DES_key_sched((Block *)stp->str_ikey, &stp->str_sched);
497068e7061SPeter Avalos 
498068e7061SPeter Avalos 	stp->str_index = sizeof(Block);
499068e7061SPeter Avalos }
500068e7061SPeter Avalos 
501068e7061SPeter Avalos void
fb64_stream_key(Block key,struct stinfo * stp)502068e7061SPeter Avalos fb64_stream_key(Block key, struct stinfo *stp)
503068e7061SPeter Avalos {
504068e7061SPeter Avalos 	memmove((void *)stp->str_ikey, (void *)key, sizeof(Block));
505*82ae7067SJohn Marino 	DES_key_sched((Block *)key, &stp->str_sched);
506068e7061SPeter Avalos 
507068e7061SPeter Avalos 	memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
508068e7061SPeter Avalos 
509068e7061SPeter Avalos 	stp->str_index = sizeof(Block);
510068e7061SPeter Avalos }
511068e7061SPeter Avalos 
512068e7061SPeter Avalos /*
513068e7061SPeter Avalos  * DES 64 bit Cipher Feedback
514068e7061SPeter Avalos  *
515068e7061SPeter Avalos  *     key --->+-----+
516068e7061SPeter Avalos  *          +->| DES |--+
517068e7061SPeter Avalos  *          |  +-----+  |
518068e7061SPeter Avalos  *	    |           v
519068e7061SPeter Avalos  *  INPUT --(--------->(+)+---> DATA
520068e7061SPeter Avalos  *          |             |
521068e7061SPeter Avalos  *	    +-------------+
522068e7061SPeter Avalos  *
523068e7061SPeter Avalos  *
524068e7061SPeter Avalos  * Given:
525068e7061SPeter Avalos  *	iV: Initial vector, 64 bits (8 bytes) long.
526068e7061SPeter Avalos  *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
527068e7061SPeter Avalos  *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
528068e7061SPeter Avalos  *
529068e7061SPeter Avalos  *	V0 = DES(iV, key)
530068e7061SPeter Avalos  *	On = Dn ^ Vn
531068e7061SPeter Avalos  *	V(n+1) = DES(On, key)
532068e7061SPeter Avalos  */
533068e7061SPeter Avalos 
534068e7061SPeter Avalos void
cfb64_encrypt(unsigned char * s,int c)535068e7061SPeter Avalos cfb64_encrypt(unsigned char *s, int c)
536068e7061SPeter Avalos {
537068e7061SPeter Avalos 	struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
538068e7061SPeter Avalos 	int idx;
539068e7061SPeter Avalos 
540068e7061SPeter Avalos 	idx = stp->str_index;
541068e7061SPeter Avalos 	while (c-- > 0) {
542068e7061SPeter Avalos 		if (idx == sizeof(Block)) {
543068e7061SPeter Avalos 			Block b;
544*82ae7067SJohn Marino 			DES_ecb_encrypt((Block *)stp->str_output, (Block *)b, &stp->str_sched, 1);
545068e7061SPeter Avalos 			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
546068e7061SPeter Avalos 			idx = 0;
547068e7061SPeter Avalos 		}
548068e7061SPeter Avalos 
549068e7061SPeter Avalos 		/* On encryption, we store (feed ^ data) which is cypher */
550068e7061SPeter Avalos 		*s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s);
551068e7061SPeter Avalos 		s++;
552068e7061SPeter Avalos 		idx++;
553068e7061SPeter Avalos 	}
554068e7061SPeter Avalos 	stp->str_index = idx;
555068e7061SPeter Avalos }
556068e7061SPeter Avalos 
557068e7061SPeter Avalos int
cfb64_decrypt(int data)558068e7061SPeter Avalos cfb64_decrypt(int data)
559068e7061SPeter Avalos {
560068e7061SPeter Avalos 	struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
561068e7061SPeter Avalos 	int idx;
562068e7061SPeter Avalos 
563068e7061SPeter Avalos 	if (data == -1) {
564068e7061SPeter Avalos 		/*
565068e7061SPeter Avalos 		 * Back up one byte.  It is assumed that we will
566068e7061SPeter Avalos 		 * never back up more than one byte.  If we do, this
567068e7061SPeter Avalos 		 * may or may not work.
568068e7061SPeter Avalos 		 */
569068e7061SPeter Avalos 		if (stp->str_index)
570068e7061SPeter Avalos 			--stp->str_index;
571068e7061SPeter Avalos 		return(0);
572068e7061SPeter Avalos 	}
573068e7061SPeter Avalos 
574068e7061SPeter Avalos 	idx = stp->str_index++;
575068e7061SPeter Avalos 	if (idx == sizeof(Block)) {
576068e7061SPeter Avalos 		Block b;
577*82ae7067SJohn Marino 		DES_ecb_encrypt((Block *)stp->str_output, (Block *)b, &stp->str_sched, 1);
578068e7061SPeter Avalos 		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
579068e7061SPeter Avalos 		stp->str_index = 1;	/* Next time will be 1 */
580068e7061SPeter Avalos 		idx = 0;		/* But now use 0 */
581068e7061SPeter Avalos 	}
582068e7061SPeter Avalos 
583068e7061SPeter Avalos 	/* On decryption we store (data) which is cypher. */
584068e7061SPeter Avalos 	stp->str_output[idx] = data;
585068e7061SPeter Avalos 	return(data ^ stp->str_feed[idx]);
586068e7061SPeter Avalos }
587068e7061SPeter Avalos 
588068e7061SPeter Avalos /*
589068e7061SPeter Avalos  * DES 64 bit Output Feedback
590068e7061SPeter Avalos  *
591068e7061SPeter Avalos  * key --->+-----+
592068e7061SPeter Avalos  *	+->| DES |--+
593068e7061SPeter Avalos  *	|  +-----+  |
594068e7061SPeter Avalos  *	+-----------+
595068e7061SPeter Avalos  *	            v
596068e7061SPeter Avalos  *  INPUT -------->(+) ----> DATA
597068e7061SPeter Avalos  *
598068e7061SPeter Avalos  * Given:
599068e7061SPeter Avalos  *	iV: Initial vector, 64 bits (8 bytes) long.
600068e7061SPeter Avalos  *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
601068e7061SPeter Avalos  *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
602068e7061SPeter Avalos  *
603068e7061SPeter Avalos  *	V0 = DES(iV, key)
604068e7061SPeter Avalos  *	V(n+1) = DES(Vn, key)
605068e7061SPeter Avalos  *	On = Dn ^ Vn
606068e7061SPeter Avalos  */
607068e7061SPeter Avalos void
ofb64_encrypt(unsigned char * s,int c)608068e7061SPeter Avalos ofb64_encrypt(unsigned char *s, int c)
609068e7061SPeter Avalos {
610068e7061SPeter Avalos 	struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
611068e7061SPeter Avalos 	int idx;
612068e7061SPeter Avalos 
613068e7061SPeter Avalos 	idx = stp->str_index;
614068e7061SPeter Avalos 	while (c-- > 0) {
615068e7061SPeter Avalos 		if (idx == sizeof(Block)) {
616068e7061SPeter Avalos 			Block b;
617*82ae7067SJohn Marino 			DES_ecb_encrypt((Block *)stp->str_feed, (Block *)b, &stp->str_sched, 1);
618068e7061SPeter Avalos 			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
619068e7061SPeter Avalos 			idx = 0;
620068e7061SPeter Avalos 		}
621068e7061SPeter Avalos 		*s++ ^= stp->str_feed[idx];
622068e7061SPeter Avalos 		idx++;
623068e7061SPeter Avalos 	}
624068e7061SPeter Avalos 	stp->str_index = idx;
625068e7061SPeter Avalos }
626068e7061SPeter Avalos 
627068e7061SPeter Avalos int
ofb64_decrypt(int data)628068e7061SPeter Avalos ofb64_decrypt(int data)
629068e7061SPeter Avalos {
630068e7061SPeter Avalos 	struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
631068e7061SPeter Avalos 	int idx;
632068e7061SPeter Avalos 
633068e7061SPeter Avalos 	if (data == -1) {
634068e7061SPeter Avalos 		/*
635068e7061SPeter Avalos 		 * Back up one byte.  It is assumed that we will
636068e7061SPeter Avalos 		 * never back up more than one byte.  If we do, this
637068e7061SPeter Avalos 		 * may or may not work.
638068e7061SPeter Avalos 		 */
639068e7061SPeter Avalos 		if (stp->str_index)
640068e7061SPeter Avalos 			--stp->str_index;
641068e7061SPeter Avalos 		return(0);
642068e7061SPeter Avalos 	}
643068e7061SPeter Avalos 
644068e7061SPeter Avalos 	idx = stp->str_index++;
645068e7061SPeter Avalos 	if (idx == sizeof(Block)) {
646068e7061SPeter Avalos 		Block b;
647*82ae7067SJohn Marino 		DES_ecb_encrypt((Block *)stp->str_feed, (Block *)b, &stp->str_sched, 1);
648068e7061SPeter Avalos 		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
649068e7061SPeter Avalos 		stp->str_index = 1;	/* Next time will be 1 */
650068e7061SPeter Avalos 		idx = 0;		/* But now use 0 */
651068e7061SPeter Avalos 	}
652068e7061SPeter Avalos 
653068e7061SPeter Avalos 	return(data ^ stp->str_feed[idx]);
654068e7061SPeter Avalos }
655068e7061SPeter Avalos # endif	/* AUTHENTICATION */
656068e7061SPeter Avalos #endif	/* ENCRYPTION */
657