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