enc_des.c revision 29181
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char sccsid[] = "@(#)enc_des.c	8.3 (Berkeley) 5/30/95";
36#endif /* not lint */
37
38#ifdef	ENCRYPTION
39# ifdef	AUTHENTICATION
40#  ifdef DES_ENCRYPTION
41#include <arpa/telnet.h>
42#include <stdio.h>
43#ifdef	__STDC__
44#include <stdlib.h>
45#endif
46
47#include <des.h>
48#include <string.h>
49#include "encrypt.h"
50#include "key-proto.h"
51#include "misc-proto.h"
52
53extern encrypt_debug_mode;
54
55#define	CFB	0
56#define	OFB	1
57
58#define	NO_SEND_IV	1
59#define	NO_RECV_IV	2
60#define	NO_KEYID	4
61#define	IN_PROGRESS	(NO_SEND_IV|NO_RECV_IV|NO_KEYID)
62#define	SUCCESS		0
63#define	FAILED		-1
64
65
66struct fb {
67	Block krbdes_key;
68	Schedule krbdes_sched;
69	Block temp_feed;
70	unsigned char fb_feed[64];
71	int need_start;
72	int state[2];
73	int keyid[2];
74	int once;
75	struct stinfo {
76		Block		str_output;
77		Block		str_feed;
78		Block		str_iv;
79		Block		str_ikey;
80		Schedule	str_sched;
81		int		str_index;
82		int		str_flagshift;
83	} streams[2];
84};
85
86static struct fb fb[2];
87
88struct keyidlist {
89	char	*keyid;
90	int	keyidlen;
91	char	*key;
92	int	keylen;
93	int	flags;
94} keyidlist [] = {
95	{ "\0", 1, 0, 0, 0 },		/* default key of zero */
96	{ 0, 0, 0, 0, 0 }
97};
98
99#define	KEYFLAG_MASK	03
100
101#define	KEYFLAG_NOINIT	00
102#define	KEYFLAG_INIT	01
103#define	KEYFLAG_OK	02
104#define	KEYFLAG_BAD	03
105
106#define	KEYFLAG_SHIFT	2
107
108#define	SHIFT_VAL(a,b)	(KEYFLAG_SHIFT*((a)+((b)*2)))
109
110#define	FB64_IV		1
111#define	FB64_IV_OK	2
112#define	FB64_IV_BAD	3
113
114
115void fb64_stream_iv P((Block, struct stinfo *));
116void fb64_init P((struct fb *));
117static int fb64_start P((struct fb *, int, int));
118int fb64_is P((unsigned char *, int, struct fb *));
119int fb64_reply P((unsigned char *, int, struct fb *));
120static void fb64_session P((Session_Key *, int, struct fb *));
121void fb64_stream_key P((Block, struct stinfo *));
122int fb64_keyid P((int, unsigned char *, int *, struct fb *));
123
124	void
125cfb64_init(server)
126	int server;
127{
128	fb64_init(&fb[CFB]);
129	fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
130	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
131	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
132}
133
134	void
135ofb64_init(server)
136	int server;
137{
138	fb64_init(&fb[OFB]);
139	fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
140	fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
141	fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
142}
143
144	void
145fb64_init(fbp)
146	register struct fb *fbp;
147{
148	memset((void *)fbp, 0, sizeof(*fbp));
149	fbp->state[0] = fbp->state[1] = FAILED;
150	fbp->fb_feed[0] = IAC;
151	fbp->fb_feed[1] = SB;
152	fbp->fb_feed[2] = TELOPT_ENCRYPT;
153	fbp->fb_feed[3] = ENCRYPT_IS;
154}
155
156/*
157 * Returns:
158 *	-1: some error.  Negotiation is done, encryption not ready.
159 *	 0: Successful, initial negotiation all done.
160 *	 1: successful, negotiation not done yet.
161 *	 2: Not yet.  Other things (like getting the key from
162 *	    Kerberos) have to happen before we can continue.
163 */
164	int
165cfb64_start(dir, server)
166	int dir;
167	int server;
168{
169	return(fb64_start(&fb[CFB], dir, server));
170}
171	int
172ofb64_start(dir, server)
173	int dir;
174	int server;
175{
176	return(fb64_start(&fb[OFB], dir, server));
177}
178
179	static int
180fb64_start(fbp, dir, server)
181	struct fb *fbp;
182	int dir;
183	int server;
184{
185	int x;
186	unsigned char *p;
187	register int state;
188
189	switch (dir) {
190	case DIR_DECRYPT:
191		/*
192		 * This is simply a request to have the other side
193		 * start output (our input).  He will negotiate an
194		 * IV so we need not look for it.
195		 */
196		state = fbp->state[dir-1];
197		if (state == FAILED)
198			state = IN_PROGRESS;
199		break;
200
201	case DIR_ENCRYPT:
202		state = fbp->state[dir-1];
203		if (state == FAILED)
204			state = IN_PROGRESS;
205		else if ((state & NO_SEND_IV) == 0)
206			break;
207
208		if (!VALIDKEY(fbp->krbdes_key)) {
209			fbp->need_start = 1;
210			break;
211		}
212		state &= ~NO_SEND_IV;
213		state |= NO_RECV_IV;
214		if (encrypt_debug_mode)
215			printf("Creating new feed\r\n");
216		/*
217		 * Create a random feed and send it over.
218		 */
219		des_new_random_key((Block *)fbp->temp_feed);
220		des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed,
221				fbp->krbdes_sched, 1);
222		p = fbp->fb_feed + 3;
223		*p++ = ENCRYPT_IS;
224		p++;
225		*p++ = FB64_IV;
226		for (x = 0; x < sizeof(Block); ++x) {
227			if ((*p++ = fbp->temp_feed[x]) == IAC)
228				*p++ = IAC;
229		}
230		*p++ = IAC;
231		*p++ = SE;
232		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
233		net_write(fbp->fb_feed, p - fbp->fb_feed);
234		break;
235	default:
236		return(FAILED);
237	}
238	return(fbp->state[dir-1] = state);
239}
240
241/*
242 * Returns:
243 *	-1: some error.  Negotiation is done, encryption not ready.
244 *	 0: Successful, initial negotiation all done.
245 *	 1: successful, negotiation not done yet.
246 */
247	int
248cfb64_is(data, cnt)
249	unsigned char *data;
250	int cnt;
251{
252	return(fb64_is(data, cnt, &fb[CFB]));
253}
254	int
255ofb64_is(data, cnt)
256	unsigned char *data;
257	int cnt;
258{
259	return(fb64_is(data, cnt, &fb[OFB]));
260}
261
262	int
263fb64_is(data, cnt, fbp)
264	unsigned char *data;
265	int cnt;
266	struct fb *fbp;
267{
268	unsigned char *p;
269	register int state = fbp->state[DIR_DECRYPT-1];
270
271	if (cnt-- < 1)
272		goto failure;
273
274	switch (*data++) {
275	case FB64_IV:
276		if (cnt != sizeof(Block)) {
277			if (encrypt_debug_mode)
278				printf("CFB64: initial vector failed on size\r\n");
279			state = FAILED;
280			goto failure;
281		}
282
283		if (encrypt_debug_mode)
284			printf("CFB64: initial vector received\r\n");
285
286		if (encrypt_debug_mode)
287			printf("Initializing Decrypt stream\r\n");
288
289		fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
290
291		p = fbp->fb_feed + 3;
292		*p++ = ENCRYPT_REPLY;
293		p++;
294		*p++ = FB64_IV_OK;
295		*p++ = IAC;
296		*p++ = SE;
297		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
298		net_write(fbp->fb_feed, p - fbp->fb_feed);
299
300		state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
301		break;
302
303	default:
304		if (encrypt_debug_mode) {
305			printf("Unknown option type: %d\r\n", *(data-1));
306			printd(data, cnt);
307			printf("\r\n");
308		}
309		/* FALL THROUGH */
310	failure:
311		/*
312		 * We failed.  Send an FB64_IV_BAD option
313		 * to the other side so it will know that
314		 * things failed.
315		 */
316		p = fbp->fb_feed + 3;
317		*p++ = ENCRYPT_REPLY;
318		p++;
319		*p++ = FB64_IV_BAD;
320		*p++ = IAC;
321		*p++ = SE;
322		printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
323		net_write(fbp->fb_feed, p - fbp->fb_feed);
324
325		break;
326	}
327	return(fbp->state[DIR_DECRYPT-1] = state);
328}
329
330/*
331 * Returns:
332 *	-1: some error.  Negotiation is done, encryption not ready.
333 *	 0: Successful, initial negotiation all done.
334 *	 1: successful, negotiation not done yet.
335 */
336	int
337cfb64_reply(data, cnt)
338	unsigned char *data;
339	int cnt;
340{
341	return(fb64_reply(data, cnt, &fb[CFB]));
342}
343	int
344ofb64_reply(data, cnt)
345	unsigned char *data;
346	int cnt;
347{
348	return(fb64_reply(data, cnt, &fb[OFB]));
349}
350
351
352	int
353fb64_reply(data, cnt, fbp)
354	unsigned char *data;
355	int cnt;
356	struct fb *fbp;
357{
358	register int state = fbp->state[DIR_ENCRYPT-1];
359
360	if (cnt-- < 1)
361		goto failure;
362
363	switch (*data++) {
364	case FB64_IV_OK:
365		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
366		if (state == FAILED)
367			state = IN_PROGRESS;
368		state &= ~NO_RECV_IV;
369		encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1);
370		break;
371
372	case FB64_IV_BAD:
373		memset(fbp->temp_feed, 0, sizeof(Block));
374		fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
375		state = FAILED;
376		break;
377
378	default:
379		if (encrypt_debug_mode) {
380			printf("Unknown option type: %d\r\n", data[-1]);
381			printd(data, cnt);
382			printf("\r\n");
383		}
384		/* FALL THROUGH */
385	failure:
386		state = FAILED;
387		break;
388	}
389	return(fbp->state[DIR_ENCRYPT-1] = state);
390}
391
392	void
393cfb64_session(key, server)
394	Session_Key *key;
395	int server;
396{
397	fb64_session(key, server, &fb[CFB]);
398}
399
400	void
401ofb64_session(key, server)
402	Session_Key *key;
403	int server;
404{
405	fb64_session(key, server, &fb[OFB]);
406}
407
408	static void
409fb64_session(key, server, fbp)
410	Session_Key *key;
411	int server;
412	struct fb *fbp;
413{
414
415	if (!key || key->type != SK_DES) {
416		if (encrypt_debug_mode)
417			printf("Can't set krbdes's session key (%d != %d)\r\n",
418				key ? key->type : -1, SK_DES);
419		return;
420	}
421	memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
422
423	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
424	fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
425
426	if (fbp->once == 0) {
427		des_set_random_generator_seed((Block *)fbp->krbdes_key);
428		fbp->once = 1;
429	}
430	des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched);
431	/*
432	 * Now look to see if krbdes_start() was was waiting for
433	 * the key to show up.  If so, go ahead an call it now
434	 * that we have the key.
435	 */
436	if (fbp->need_start) {
437		fbp->need_start = 0;
438		fb64_start(fbp, DIR_ENCRYPT, server);
439	}
440}
441
442/*
443 * We only accept a keyid of 0.  If we get a keyid of
444 * 0, then mark the state as SUCCESS.
445 */
446	int
447cfb64_keyid(dir, kp, lenp)
448	int dir, *lenp;
449	unsigned char *kp;
450{
451	return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
452}
453
454	int
455ofb64_keyid(dir, kp, lenp)
456	int dir, *lenp;
457	unsigned char *kp;
458{
459	return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
460}
461
462	int
463fb64_keyid(dir, kp, lenp, fbp)
464	int dir, *lenp;
465	unsigned char *kp;
466	struct fb *fbp;
467{
468	register int state = fbp->state[dir-1];
469
470	if (*lenp != 1 || (*kp != '\0')) {
471		*lenp = 0;
472		return(state);
473	}
474
475	if (state == FAILED)
476		state = IN_PROGRESS;
477
478	state &= ~NO_KEYID;
479
480	return(fbp->state[dir-1] = state);
481}
482
483	void
484fb64_printsub(data, cnt, buf, buflen, type)
485	unsigned char *data, *buf, *type;
486	int cnt, buflen;
487{
488	char lbuf[32];
489	register int i;
490	char *cp;
491
492	buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
493	buflen -= 1;
494
495	switch(data[2]) {
496	case FB64_IV:
497		sprintf(lbuf, "%s_IV", type);
498		cp = lbuf;
499		goto common;
500
501	case FB64_IV_OK:
502		sprintf(lbuf, "%s_IV_OK", type);
503		cp = lbuf;
504		goto common;
505
506	case FB64_IV_BAD:
507		sprintf(lbuf, "%s_IV_BAD", type);
508		cp = lbuf;
509		goto common;
510
511	default:
512		sprintf(lbuf, " %d (unknown)", data[2]);
513		cp = lbuf;
514	common:
515		for (; (buflen > 0) && (*buf = *cp++); buf++)
516			buflen--;
517		for (i = 3; i < cnt; i++) {
518			sprintf(lbuf, " %d", data[i]);
519			for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
520				buflen--;
521		}
522		break;
523	}
524}
525
526	void
527cfb64_printsub(data, cnt, buf, buflen)
528	unsigned char *data, *buf;
529	int cnt, buflen;
530{
531	fb64_printsub(data, cnt, buf, buflen, "CFB64");
532}
533
534	void
535ofb64_printsub(data, cnt, buf, buflen)
536	unsigned char *data, *buf;
537	int cnt, buflen;
538{
539	fb64_printsub(data, cnt, buf, buflen, "OFB64");
540}
541
542	void
543fb64_stream_iv(seed, stp)
544	Block seed;
545	register struct stinfo *stp;
546{
547
548	memmove((void *)stp->str_iv, (void *)seed, sizeof(Block));
549	memmove((void *)stp->str_output, (void *)seed, sizeof(Block));
550
551	des_key_sched((Block *)stp->str_ikey, stp->str_sched);
552
553	stp->str_index = sizeof(Block);
554}
555
556	void
557fb64_stream_key(key, stp)
558	Block key;
559	register struct stinfo *stp;
560{
561	memmove((void *)stp->str_ikey, (void *)key, sizeof(Block));
562	des_key_sched((Block *)key, stp->str_sched);
563
564	memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
565
566	stp->str_index = sizeof(Block);
567}
568
569/*
570 * DES 64 bit Cipher Feedback
571 *
572 *     key --->+-----+
573 *          +->| DES |--+
574 *          |  +-----+  |
575 *	    |           v
576 *  INPUT --(--------->(+)+---> DATA
577 *          |             |
578 *	    +-------------+
579 *
580 *
581 * Given:
582 *	iV: Initial vector, 64 bits (8 bytes) long.
583 *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
584 *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
585 *
586 *	V0 = DES(iV, key)
587 *	On = Dn ^ Vn
588 *	V(n+1) = DES(On, key)
589 */
590
591	void
592cfb64_encrypt(s, c)
593	register unsigned char *s;
594	int c;
595{
596	register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
597	register int index;
598
599	index = stp->str_index;
600	while (c-- > 0) {
601		if (index == sizeof(Block)) {
602			Block b;
603			des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
604			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
605			index = 0;
606		}
607
608		/* On encryption, we store (feed ^ data) which is cypher */
609		*s = stp->str_output[index] = (stp->str_feed[index] ^ *s);
610		s++;
611		index++;
612	}
613	stp->str_index = index;
614}
615
616	int
617cfb64_decrypt(data)
618	int data;
619{
620	register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
621	int index;
622
623	if (data == -1) {
624		/*
625		 * Back up one byte.  It is assumed that we will
626		 * never back up more than one byte.  If we do, this
627		 * may or may not work.
628		 */
629		if (stp->str_index)
630			--stp->str_index;
631		return(0);
632	}
633
634	index = stp->str_index++;
635	if (index == sizeof(Block)) {
636		Block b;
637		des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
638		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
639		stp->str_index = 1;	/* Next time will be 1 */
640		index = 0;		/* But now use 0 */
641	}
642
643	/* On decryption we store (data) which is cypher. */
644	stp->str_output[index] = data;
645	return(data ^ stp->str_feed[index]);
646}
647
648/*
649 * DES 64 bit Output Feedback
650 *
651 * key --->+-----+
652 *	+->| DES |--+
653 *	|  +-----+  |
654 *	+-----------+
655 *	            v
656 *  INPUT -------->(+) ----> DATA
657 *
658 * Given:
659 *	iV: Initial vector, 64 bits (8 bytes) long.
660 *	Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
661 *	On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
662 *
663 *	V0 = DES(iV, key)
664 *	V(n+1) = DES(Vn, key)
665 *	On = Dn ^ Vn
666 */
667	void
668ofb64_encrypt(s, c)
669	register unsigned char *s;
670	int c;
671{
672	register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
673	register int index;
674
675	index = stp->str_index;
676	while (c-- > 0) {
677		if (index == sizeof(Block)) {
678			Block b;
679			des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
680			memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
681			index = 0;
682		}
683		*s++ ^= stp->str_feed[index];
684		index++;
685	}
686	stp->str_index = index;
687}
688
689	int
690ofb64_decrypt(data)
691	int data;
692{
693	register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
694	int index;
695
696	if (data == -1) {
697		/*
698		 * Back up one byte.  It is assumed that we will
699		 * never back up more than one byte.  If we do, this
700		 * may or may not work.
701		 */
702		if (stp->str_index)
703			--stp->str_index;
704		return(0);
705	}
706
707	index = stp->str_index++;
708	if (index == sizeof(Block)) {
709		Block b;
710		des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
711		memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
712		stp->str_index = 1;	/* Next time will be 1 */
713		index = 0;		/* But now use 0 */
714	}
715
716	return(data ^ stp->str_feed[index]);
717}
718#  endif /* DES_ENCRYPTION */
719# endif	/* AUTHENTICATION */
720#endif	/* ENCRYPTION */
721