1 /* $NetBSD: enc_des.c,v 1.12 2005/02/06 05:53:07 perry Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; */
37 __RCSID("$NetBSD: enc_des.c,v 1.12 2005/02/06 05:53:07 perry Exp $");
42 # ifdef AUTHENTICATION
43 # ifdef DES_ENCRYPTION
44 #include <arpa/telnet.h>
51 #include "key-proto.h"
52 #include "misc-proto.h"
60 #define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID)
67 Schedule krbdes_sched
;
69 unsigned char fb_feed
[64];
85 static struct fb fb
[2];
94 { "\0", 1, 0, 0, 0 }, /* default key of zero */
98 #define KEYFLAG_MASK 03
100 #define KEYFLAG_NOINIT 00
101 #define KEYFLAG_INIT 01
102 #define KEYFLAG_OK 02
103 #define KEYFLAG_BAD 03
105 #define KEYFLAG_SHIFT 2
107 #define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2)))
111 #define FB64_IV_BAD 3
114 void fb64_stream_iv(Block
, struct stinfo
*);
115 void fb64_init(struct fb
*);
116 static int fb64_start(struct fb
*, int, int);
117 int fb64_is(unsigned char *, int, struct fb
*);
118 int fb64_reply(unsigned char *, int, struct fb
*);
119 static void fb64_session(Session_Key
*, int, struct fb
*);
120 void fb64_stream_key(Block
*, struct stinfo
*);
121 int fb64_keyid(int, unsigned char *, int *, struct fb
*);
128 fb
[CFB
].fb_feed
[4] = ENCTYPE_DES_CFB64
;
129 fb
[CFB
].streams
[0].str_flagshift
= SHIFT_VAL(0, CFB
);
130 fb
[CFB
].streams
[1].str_flagshift
= SHIFT_VAL(1, CFB
);
138 fb
[OFB
].fb_feed
[4] = ENCTYPE_DES_OFB64
;
139 fb
[CFB
].streams
[0].str_flagshift
= SHIFT_VAL(0, OFB
);
140 fb
[CFB
].streams
[1].str_flagshift
= SHIFT_VAL(1, OFB
);
145 register struct fb
*fbp
;
147 memset((void *)fbp
, 0, sizeof(*fbp
));
148 fbp
->state
[0] = fbp
->state
[1] = FAILED
;
149 fbp
->fb_feed
[0] = IAC
;
150 fbp
->fb_feed
[1] = SB
;
151 fbp
->fb_feed
[2] = TELOPT_ENCRYPT
;
152 fbp
->fb_feed
[3] = ENCRYPT_IS
;
157 * -1: some error. Negotiation is done, encryption not ready.
158 * 0: Successful, initial negotiation all done.
159 * 1: successful, negotiation not done yet.
160 * 2: Not yet. Other things (like getting the key from
161 * Kerberos) have to happen before we can continue.
164 cfb64_start(dir
, server
)
168 return(fb64_start(&fb
[CFB
], dir
, server
));
171 ofb64_start(dir
, server
)
175 return(fb64_start(&fb
[OFB
], dir
, server
));
179 fb64_start(fbp
, dir
, server
)
191 * This is simply a request to have the other side
192 * start output (our input). He will negotiate an
193 * IV so we need not look for it.
195 state
= fbp
->state
[dir
-1];
201 state
= fbp
->state
[dir
-1];
204 else if ((state
& NO_SEND_IV
) == 0)
207 if (!VALIDKEY(fbp
->krbdes_key
)) {
211 state
&= ~NO_SEND_IV
;
213 if (encrypt_debug_mode
)
214 printf("Creating new feed\r\n");
216 * Create a random feed and send it over.
218 des_new_random_key(&fbp
->temp_feed
);
219 des_ecb_encrypt(&fbp
->temp_feed
, &fbp
->temp_feed
,
220 fbp
->krbdes_sched
, 1);
221 p
= fbp
->fb_feed
+ 3;
225 for (x
= 0; x
< sizeof(Block
); ++x
) {
226 if ((*p
++ = fbp
->temp_feed
[x
]) == IAC
)
231 printsub('>', &fbp
->fb_feed
[2], p
- &fbp
->fb_feed
[2]);
232 telnet_net_write(fbp
->fb_feed
, p
- fbp
->fb_feed
);
237 return(fbp
->state
[dir
-1] = state
);
242 * -1: some error. Negotiation is done, encryption not ready.
243 * 0: Successful, initial negotiation all done.
244 * 1: successful, negotiation not done yet.
251 return(fb64_is(data
, cnt
, &fb
[CFB
]));
258 return(fb64_is(data
, cnt
, &fb
[OFB
]));
262 fb64_is(data
, cnt
, fbp
)
268 register int state
= fbp
->state
[DIR_DECRYPT
-1];
275 if (cnt
!= sizeof(Block
)) {
276 if (encrypt_debug_mode
)
277 printf("CFB64: initial vector failed on size\r\n");
282 if (encrypt_debug_mode
)
283 printf("CFB64: initial vector received\r\n");
285 if (encrypt_debug_mode
)
286 printf("Initializing Decrypt stream\r\n");
288 fb64_stream_iv((void *)data
, &fbp
->streams
[DIR_DECRYPT
-1]);
290 p
= fbp
->fb_feed
+ 3;
291 *p
++ = ENCRYPT_REPLY
;
296 printsub('>', &fbp
->fb_feed
[2], p
- &fbp
->fb_feed
[2]);
297 telnet_net_write(fbp
->fb_feed
, p
- fbp
->fb_feed
);
299 state
= fbp
->state
[DIR_DECRYPT
-1] = IN_PROGRESS
;
303 if (encrypt_debug_mode
) {
304 printf("Unknown option type: %d\r\n", *(data
-1));
311 * We failed. Send an FB64_IV_BAD option
312 * to the other side so it will know that
315 p
= fbp
->fb_feed
+ 3;
316 *p
++ = ENCRYPT_REPLY
;
321 printsub('>', &fbp
->fb_feed
[2], p
- &fbp
->fb_feed
[2]);
322 telnet_net_write(fbp
->fb_feed
, p
- fbp
->fb_feed
);
326 return(fbp
->state
[DIR_DECRYPT
-1] = state
);
331 * -1: some error. Negotiation is done, encryption not ready.
332 * 0: Successful, initial negotiation all done.
333 * 1: successful, negotiation not done yet.
336 cfb64_reply(data
, cnt
)
340 return(fb64_reply(data
, cnt
, &fb
[CFB
]));
343 ofb64_reply(data
, cnt
)
347 return(fb64_reply(data
, cnt
, &fb
[OFB
]));
352 fb64_reply(data
, cnt
, fbp
)
357 register int state
= fbp
->state
[DIR_ENCRYPT
-1];
364 fb64_stream_iv(fbp
->temp_feed
, &fbp
->streams
[DIR_ENCRYPT
-1]);
367 state
&= ~NO_RECV_IV
;
368 encrypt_send_keyid(DIR_ENCRYPT
, (unsigned char *)"\0", 1, 1);
372 memset(fbp
->temp_feed
, 0, sizeof(Block
));
373 fb64_stream_iv(fbp
->temp_feed
, &fbp
->streams
[DIR_ENCRYPT
-1]);
378 if (encrypt_debug_mode
) {
379 printf("Unknown option type: %d\r\n", data
[-1]);
388 return(fbp
->state
[DIR_ENCRYPT
-1] = state
);
392 cfb64_session(key
, server
)
396 fb64_session(key
, server
, &fb
[CFB
]);
400 ofb64_session(key
, server
)
404 fb64_session(key
, server
, &fb
[OFB
]);
408 fb64_session(key
, server
, fbp
)
414 if (!key
|| key
->type
!= SK_DES
) {
415 if (encrypt_debug_mode
)
416 printf("Can't set krbdes's session key (%d != %d)\r\n",
417 key
? key
->type
: -1, SK_DES
);
420 memmove((void *)fbp
->krbdes_key
, (void *)key
->data
, sizeof(Block
));
422 fb64_stream_key(&fbp
->krbdes_key
, &fbp
->streams
[DIR_ENCRYPT
-1]);
423 fb64_stream_key(&fbp
->krbdes_key
, &fbp
->streams
[DIR_DECRYPT
-1]);
425 if (fbp
->once
== 0) {
426 des_init_random_number_generator(&fbp
->krbdes_key
);
429 des_key_sched(&fbp
->krbdes_key
, fbp
->krbdes_sched
);
431 * Now look to see if krbdes_start() was was waiting for
432 * the key to show up. If so, go ahead an call it now
433 * that we have the key.
435 if (fbp
->need_start
) {
437 fb64_start(fbp
, DIR_ENCRYPT
, server
);
442 * We only accept a keyid of 0. If we get a keyid of
443 * 0, then mark the state as SUCCESS.
446 cfb64_keyid(dir
, kp
, lenp
)
450 return(fb64_keyid(dir
, kp
, lenp
, &fb
[CFB
]));
454 ofb64_keyid(dir
, kp
, lenp
)
458 return(fb64_keyid(dir
, kp
, lenp
, &fb
[OFB
]));
462 fb64_keyid(dir
, kp
, lenp
, fbp
)
467 register int state
= fbp
->state
[dir
-1];
469 if (*lenp
!= 1 || (*kp
!= '\0')) {
479 return(fbp
->state
[dir
-1] = state
);
483 fb64_printsub(data
, cnt
, buf
, buflen
, type
)
484 unsigned char *data
, *buf
, *type
;
491 buf
[buflen
-1] = '\0'; /* make sure it's NULL terminated */
496 snprintf(lbuf
, sizeof(lbuf
), "%s_IV", type
);
501 snprintf(lbuf
, sizeof(lbuf
), "%s_IV_OK", type
);
506 snprintf(lbuf
, sizeof(lbuf
), "%s_IV_BAD", type
);
511 snprintf(lbuf
, sizeof(lbuf
), " %d (unknown)", data
[2]);
514 for (; (buflen
> 0) && (*buf
= *cp
++); buf
++)
516 for (i
= 3; i
< cnt
; i
++) {
517 snprintf(lbuf
, sizeof(lbuf
), " %d", data
[i
]);
518 for (cp
= lbuf
; (buflen
> 0) && (*buf
= *cp
++); buf
++)
526 cfb64_printsub(data
, cnt
, buf
, buflen
)
527 unsigned char *data
, *buf
;
530 fb64_printsub(data
, cnt
, buf
, buflen
, "CFB64");
534 ofb64_printsub(data
, cnt
, buf
, buflen
)
535 unsigned char *data
, *buf
;
538 fb64_printsub(data
, cnt
, buf
, buflen
, "OFB64");
542 fb64_stream_iv(seed
, stp
)
544 register struct stinfo
*stp
;
547 memmove((void *)stp
->str_iv
, (void *)seed
, sizeof(Block
));
548 memmove((void *)stp
->str_output
, (void *)seed
, sizeof(Block
));
550 des_key_sched(&stp
->str_ikey
, stp
->str_sched
);
552 stp
->str_index
= sizeof(Block
);
556 fb64_stream_key(key
, stp
)
558 register struct stinfo
*stp
;
560 memmove((void *)stp
->str_ikey
, (void *)key
, sizeof(Block
));
561 des_key_sched(key
, stp
->str_sched
);
563 memmove((void *)stp
->str_output
, (void *)stp
->str_iv
, sizeof(Block
));
565 stp
->str_index
= sizeof(Block
);
569 * DES 64 bit Cipher Feedback
575 * INPUT --(--------->(+)+---> DATA
581 * iV: Initial vector, 64 bits (8 bytes) long.
582 * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
583 * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
587 * V(n+1) = DES(On, key)
592 register unsigned char *s
;
595 register struct stinfo
*stp
= &fb
[CFB
].streams
[DIR_ENCRYPT
-1];
598 idx
= stp
->str_index
;
600 if (idx
== sizeof(Block
)) {
602 des_ecb_encrypt(&stp
->str_output
, &b
, stp
->str_sched
, 1);
603 memmove((void *)stp
->str_feed
, (void *)b
, sizeof(Block
));
607 /* On encryption, we store (feed ^ data) which is cypher */
608 *s
= stp
->str_output
[idx
] = (stp
->str_feed
[idx
] ^ *s
);
612 stp
->str_index
= idx
;
619 register struct stinfo
*stp
= &fb
[CFB
].streams
[DIR_DECRYPT
-1];
624 * Back up one byte. It is assumed that we will
625 * never back up more than one byte. If we do, this
626 * may or may not work.
633 idx
= stp
->str_index
++;
634 if (idx
== sizeof(Block
)) {
636 des_ecb_encrypt(&stp
->str_output
, &b
, stp
->str_sched
, 1);
637 memmove((void *)stp
->str_feed
, (void *)b
, sizeof(Block
));
638 stp
->str_index
= 1; /* Next time will be 1 */
639 idx
= 0; /* But now use 0 */
642 /* On decryption we store (data) which is cypher. */
643 stp
->str_output
[idx
] = data
;
644 return(data
^ stp
->str_feed
[idx
]);
648 * DES 64 bit Output Feedback
655 * INPUT -------->(+) ----> DATA
658 * iV: Initial vector, 64 bits (8 bytes) long.
659 * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
660 * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
663 * V(n+1) = DES(Vn, key)
668 register unsigned char *s
;
671 register struct stinfo
*stp
= &fb
[OFB
].streams
[DIR_ENCRYPT
-1];
674 idx
= stp
->str_index
;
676 if (idx
== sizeof(Block
)) {
678 des_ecb_encrypt(&stp
->str_feed
, &b
, stp
->str_sched
, 1);
679 memmove((void *)stp
->str_feed
, (void *)b
, sizeof(Block
));
682 *s
++ ^= stp
->str_feed
[idx
];
685 stp
->str_index
= idx
;
692 register struct stinfo
*stp
= &fb
[OFB
].streams
[DIR_DECRYPT
-1];
697 * Back up one byte. It is assumed that we will
698 * never back up more than one byte. If we do, this
699 * may or may not work.
706 idx
= stp
->str_index
++;
707 if (idx
== sizeof(Block
)) {
709 des_ecb_encrypt(&stp
->str_feed
, &b
, stp
->str_sched
, 1);
710 memmove((void *)stp
->str_feed
, (void *)b
, sizeof(Block
));
711 stp
->str_index
= 1; /* Next time will be 1 */
712 idx
= 0; /* But now use 0 */
715 return(data
^ stp
->str_feed
[idx
]);
717 # endif /* DES_ENCRYPTION */
718 # endif /* AUTHENTICATION */
719 #endif /* ENCRYPTION */