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