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