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. 1381cb6ddcSMark Murray * 3. All advertising materials mentioning features or use of this software 1481cb6ddcSMark Murray * must display the following acknowledgement: 1581cb6ddcSMark Murray * This product includes software developed by the University of 1681cb6ddcSMark Murray * California, Berkeley and its contributors. 1781cb6ddcSMark Murray * 4. Neither the name of the University nor the names of its contributors 1881cb6ddcSMark Murray * may be used to endorse or promote products derived from this software 1981cb6ddcSMark Murray * without specific prior written permission. 2081cb6ddcSMark Murray * 2181cb6ddcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2281cb6ddcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2381cb6ddcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2481cb6ddcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2581cb6ddcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2681cb6ddcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2781cb6ddcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2881cb6ddcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2981cb6ddcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3081cb6ddcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3181cb6ddcSMark Murray * SUCH DAMAGE. 32bf4f84d4SMark Murray * 33bf4f84d4SMark Murray * $FreeBSD$ 3481cb6ddcSMark Murray */ 3581cb6ddcSMark Murray 3681cb6ddcSMark Murray #ifndef lint 3704c426ccSMark Murray static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; 3881cb6ddcSMark Murray #endif /* not lint */ 3981cb6ddcSMark Murray 4081cb6ddcSMark Murray #ifdef ENCRYPTION 4181cb6ddcSMark Murray # ifdef AUTHENTICATION 4281cb6ddcSMark Murray # ifdef DES_ENCRYPTION 4381cb6ddcSMark Murray #include <arpa/telnet.h> 4481cb6ddcSMark Murray #include <stdio.h> 4581cb6ddcSMark Murray #ifdef __STDC__ 4681cb6ddcSMark Murray #include <stdlib.h> 4781cb6ddcSMark Murray #endif 4881cb6ddcSMark Murray 49bf4f84d4SMark Murray #include <openssl/des.h> 5004c426ccSMark Murray #include <string.h> 5181cb6ddcSMark Murray #include "encrypt.h" 5281cb6ddcSMark Murray #include "key-proto.h" 5381cb6ddcSMark Murray #include "misc-proto.h" 5481cb6ddcSMark Murray 5521f083c0SMark Murray extern int encrypt_debug_mode; 5621f083c0SMark Murray void des_set_random_generator_seed(des_cblock *); /* XXX */ 5781cb6ddcSMark Murray 5881cb6ddcSMark Murray #define CFB 0 5981cb6ddcSMark Murray #define OFB 1 6081cb6ddcSMark Murray 6181cb6ddcSMark Murray #define NO_SEND_IV 1 6281cb6ddcSMark Murray #define NO_RECV_IV 2 6381cb6ddcSMark Murray #define NO_KEYID 4 6481cb6ddcSMark Murray #define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) 6581cb6ddcSMark Murray #define SUCCESS 0 6681cb6ddcSMark Murray #define FAILED -1 6781cb6ddcSMark Murray 6881cb6ddcSMark Murray 6981cb6ddcSMark Murray struct fb { 7081cb6ddcSMark Murray Block krbdes_key; 7181cb6ddcSMark Murray Schedule krbdes_sched; 7281cb6ddcSMark Murray Block temp_feed; 7381cb6ddcSMark Murray unsigned char fb_feed[64]; 7481cb6ddcSMark Murray int need_start; 7581cb6ddcSMark Murray int state[2]; 7681cb6ddcSMark Murray int keyid[2]; 7781cb6ddcSMark Murray int once; 7881cb6ddcSMark Murray struct stinfo { 7981cb6ddcSMark Murray Block str_output; 8081cb6ddcSMark Murray Block str_feed; 8181cb6ddcSMark Murray Block str_iv; 8281cb6ddcSMark Murray Block str_ikey; 8381cb6ddcSMark Murray Schedule str_sched; 8481cb6ddcSMark Murray int str_index; 8581cb6ddcSMark Murray int str_flagshift; 8681cb6ddcSMark Murray } streams[2]; 8781cb6ddcSMark Murray }; 8881cb6ddcSMark Murray 8981cb6ddcSMark Murray static struct fb fb[2]; 9081cb6ddcSMark Murray 9181cb6ddcSMark Murray struct keyidlist { 9281cb6ddcSMark Murray char *keyid; 9381cb6ddcSMark Murray int keyidlen; 9481cb6ddcSMark Murray char *key; 9581cb6ddcSMark Murray int keylen; 9681cb6ddcSMark Murray int flags; 9781cb6ddcSMark Murray } keyidlist [] = { 9881cb6ddcSMark Murray { "\0", 1, 0, 0, 0 }, /* default key of zero */ 9981cb6ddcSMark Murray { 0, 0, 0, 0, 0 } 10081cb6ddcSMark Murray }; 10181cb6ddcSMark Murray 10281cb6ddcSMark Murray #define KEYFLAG_MASK 03 10381cb6ddcSMark Murray 10481cb6ddcSMark Murray #define KEYFLAG_NOINIT 00 10581cb6ddcSMark Murray #define KEYFLAG_INIT 01 10681cb6ddcSMark Murray #define KEYFLAG_OK 02 10781cb6ddcSMark Murray #define KEYFLAG_BAD 03 10881cb6ddcSMark Murray 10981cb6ddcSMark Murray #define KEYFLAG_SHIFT 2 11081cb6ddcSMark Murray 11181cb6ddcSMark Murray #define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) 11281cb6ddcSMark Murray 11381cb6ddcSMark Murray #define FB64_IV 1 11481cb6ddcSMark Murray #define FB64_IV_OK 2 11581cb6ddcSMark Murray #define FB64_IV_BAD 3 11681cb6ddcSMark Murray 11781cb6ddcSMark Murray 11881cb6ddcSMark Murray void fb64_stream_iv P((Block, struct stinfo *)); 11981cb6ddcSMark Murray void fb64_init P((struct fb *)); 12081cb6ddcSMark Murray static int fb64_start P((struct fb *, int, int)); 12181cb6ddcSMark Murray int fb64_is P((unsigned char *, int, struct fb *)); 12281cb6ddcSMark Murray int fb64_reply P((unsigned char *, int, struct fb *)); 12381cb6ddcSMark Murray static void fb64_session P((Session_Key *, int, struct fb *)); 12481cb6ddcSMark Murray void fb64_stream_key P((Block, struct stinfo *)); 12581cb6ddcSMark Murray int fb64_keyid P((int, unsigned char *, int *, struct fb *)); 12681cb6ddcSMark Murray 12781cb6ddcSMark Murray void 12881cb6ddcSMark Murray cfb64_init(server) 12981cb6ddcSMark Murray int server; 13081cb6ddcSMark Murray { 13181cb6ddcSMark Murray fb64_init(&fb[CFB]); 13281cb6ddcSMark Murray fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; 13381cb6ddcSMark Murray fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); 13481cb6ddcSMark Murray fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); 13581cb6ddcSMark Murray } 13681cb6ddcSMark Murray 13781cb6ddcSMark Murray void 13881cb6ddcSMark Murray ofb64_init(server) 13981cb6ddcSMark Murray int server; 14081cb6ddcSMark Murray { 14181cb6ddcSMark Murray fb64_init(&fb[OFB]); 14281cb6ddcSMark Murray fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; 14381cb6ddcSMark Murray fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); 14481cb6ddcSMark Murray fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); 14581cb6ddcSMark Murray } 14681cb6ddcSMark Murray 14781cb6ddcSMark Murray void 14881cb6ddcSMark Murray fb64_init(fbp) 14981cb6ddcSMark Murray register struct fb *fbp; 15081cb6ddcSMark Murray { 15181cb6ddcSMark Murray memset((void *)fbp, 0, sizeof(*fbp)); 15281cb6ddcSMark Murray fbp->state[0] = fbp->state[1] = FAILED; 15381cb6ddcSMark Murray fbp->fb_feed[0] = IAC; 15481cb6ddcSMark Murray fbp->fb_feed[1] = SB; 15581cb6ddcSMark Murray fbp->fb_feed[2] = TELOPT_ENCRYPT; 15681cb6ddcSMark Murray fbp->fb_feed[3] = ENCRYPT_IS; 15781cb6ddcSMark Murray } 15881cb6ddcSMark Murray 15981cb6ddcSMark Murray /* 16081cb6ddcSMark Murray * Returns: 16181cb6ddcSMark Murray * -1: some error. Negotiation is done, encryption not ready. 16281cb6ddcSMark Murray * 0: Successful, initial negotiation all done. 16381cb6ddcSMark Murray * 1: successful, negotiation not done yet. 16481cb6ddcSMark Murray * 2: Not yet. Other things (like getting the key from 16581cb6ddcSMark Murray * Kerberos) have to happen before we can continue. 16681cb6ddcSMark Murray */ 16781cb6ddcSMark Murray int 16881cb6ddcSMark Murray cfb64_start(dir, server) 16981cb6ddcSMark Murray int dir; 17081cb6ddcSMark Murray int server; 17181cb6ddcSMark Murray { 17281cb6ddcSMark Murray return(fb64_start(&fb[CFB], dir, server)); 17381cb6ddcSMark Murray } 17481cb6ddcSMark Murray int 17581cb6ddcSMark Murray ofb64_start(dir, server) 17681cb6ddcSMark Murray int dir; 17781cb6ddcSMark Murray int server; 17881cb6ddcSMark Murray { 17981cb6ddcSMark Murray return(fb64_start(&fb[OFB], dir, server)); 18081cb6ddcSMark Murray } 18181cb6ddcSMark Murray 18281cb6ddcSMark Murray static int 18381cb6ddcSMark Murray fb64_start(fbp, dir, server) 18481cb6ddcSMark Murray struct fb *fbp; 18581cb6ddcSMark Murray int dir; 18681cb6ddcSMark Murray int server; 18781cb6ddcSMark Murray { 18881cb6ddcSMark Murray int x; 18981cb6ddcSMark Murray unsigned char *p; 19081cb6ddcSMark Murray register int state; 19181cb6ddcSMark Murray 19281cb6ddcSMark Murray switch (dir) { 19381cb6ddcSMark Murray case DIR_DECRYPT: 19481cb6ddcSMark Murray /* 19581cb6ddcSMark Murray * This is simply a request to have the other side 19681cb6ddcSMark Murray * start output (our input). He will negotiate an 19781cb6ddcSMark Murray * IV so we need not look for it. 19881cb6ddcSMark Murray */ 19981cb6ddcSMark Murray state = fbp->state[dir-1]; 20081cb6ddcSMark Murray if (state == FAILED) 20181cb6ddcSMark Murray state = IN_PROGRESS; 20281cb6ddcSMark Murray break; 20381cb6ddcSMark Murray 20481cb6ddcSMark Murray case DIR_ENCRYPT: 20581cb6ddcSMark Murray state = fbp->state[dir-1]; 20681cb6ddcSMark Murray if (state == FAILED) 20781cb6ddcSMark Murray state = IN_PROGRESS; 20881cb6ddcSMark Murray else if ((state & NO_SEND_IV) == 0) 20981cb6ddcSMark Murray break; 21081cb6ddcSMark Murray 21181cb6ddcSMark Murray if (!VALIDKEY(fbp->krbdes_key)) { 21281cb6ddcSMark Murray fbp->need_start = 1; 21381cb6ddcSMark Murray break; 21481cb6ddcSMark Murray } 21581cb6ddcSMark Murray state &= ~NO_SEND_IV; 21681cb6ddcSMark Murray state |= NO_RECV_IV; 21781cb6ddcSMark Murray if (encrypt_debug_mode) 21881cb6ddcSMark Murray printf("Creating new feed\r\n"); 21981cb6ddcSMark Murray /* 22081cb6ddcSMark Murray * Create a random feed and send it over. 22181cb6ddcSMark Murray */ 22204c426ccSMark Murray des_new_random_key((Block *)fbp->temp_feed); 22304c426ccSMark Murray des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, 22481cb6ddcSMark Murray fbp->krbdes_sched, 1); 22581cb6ddcSMark Murray p = fbp->fb_feed + 3; 22681cb6ddcSMark Murray *p++ = ENCRYPT_IS; 22781cb6ddcSMark Murray p++; 22881cb6ddcSMark Murray *p++ = FB64_IV; 22981cb6ddcSMark Murray for (x = 0; x < sizeof(Block); ++x) { 23081cb6ddcSMark Murray if ((*p++ = fbp->temp_feed[x]) == IAC) 23181cb6ddcSMark Murray *p++ = IAC; 23281cb6ddcSMark Murray } 23381cb6ddcSMark Murray *p++ = IAC; 23481cb6ddcSMark Murray *p++ = SE; 23581cb6ddcSMark Murray printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 23681cb6ddcSMark Murray net_write(fbp->fb_feed, p - fbp->fb_feed); 23781cb6ddcSMark Murray break; 23881cb6ddcSMark Murray default: 23981cb6ddcSMark Murray return(FAILED); 24081cb6ddcSMark Murray } 24181cb6ddcSMark Murray return(fbp->state[dir-1] = state); 24281cb6ddcSMark Murray } 24381cb6ddcSMark Murray 24481cb6ddcSMark Murray /* 24581cb6ddcSMark Murray * Returns: 24681cb6ddcSMark Murray * -1: some error. Negotiation is done, encryption not ready. 24781cb6ddcSMark Murray * 0: Successful, initial negotiation all done. 24881cb6ddcSMark Murray * 1: successful, negotiation not done yet. 24981cb6ddcSMark Murray */ 25081cb6ddcSMark Murray int 25181cb6ddcSMark Murray cfb64_is(data, cnt) 25281cb6ddcSMark Murray unsigned char *data; 25381cb6ddcSMark Murray int cnt; 25481cb6ddcSMark Murray { 25581cb6ddcSMark Murray return(fb64_is(data, cnt, &fb[CFB])); 25681cb6ddcSMark Murray } 25781cb6ddcSMark Murray int 25881cb6ddcSMark Murray ofb64_is(data, cnt) 25981cb6ddcSMark Murray unsigned char *data; 26081cb6ddcSMark Murray int cnt; 26181cb6ddcSMark Murray { 26281cb6ddcSMark Murray return(fb64_is(data, cnt, &fb[OFB])); 26381cb6ddcSMark Murray } 26481cb6ddcSMark Murray 26581cb6ddcSMark Murray int 26681cb6ddcSMark Murray fb64_is(data, cnt, fbp) 26781cb6ddcSMark Murray unsigned char *data; 26881cb6ddcSMark Murray int cnt; 26981cb6ddcSMark Murray struct fb *fbp; 27081cb6ddcSMark Murray { 27181cb6ddcSMark Murray unsigned char *p; 27281cb6ddcSMark Murray register int state = fbp->state[DIR_DECRYPT-1]; 27381cb6ddcSMark Murray 27481cb6ddcSMark Murray if (cnt-- < 1) 27581cb6ddcSMark Murray goto failure; 27681cb6ddcSMark Murray 27781cb6ddcSMark Murray switch (*data++) { 27881cb6ddcSMark Murray case FB64_IV: 27981cb6ddcSMark Murray if (cnt != sizeof(Block)) { 28081cb6ddcSMark Murray if (encrypt_debug_mode) 28181cb6ddcSMark Murray printf("CFB64: initial vector failed on size\r\n"); 28281cb6ddcSMark Murray state = FAILED; 28381cb6ddcSMark Murray goto failure; 28481cb6ddcSMark Murray } 28581cb6ddcSMark Murray 28681cb6ddcSMark Murray if (encrypt_debug_mode) 28781cb6ddcSMark Murray printf("CFB64: initial vector received\r\n"); 28881cb6ddcSMark Murray 28981cb6ddcSMark Murray if (encrypt_debug_mode) 29081cb6ddcSMark Murray printf("Initializing Decrypt stream\r\n"); 29181cb6ddcSMark Murray 29281cb6ddcSMark Murray fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); 29381cb6ddcSMark Murray 29481cb6ddcSMark Murray p = fbp->fb_feed + 3; 29581cb6ddcSMark Murray *p++ = ENCRYPT_REPLY; 29681cb6ddcSMark Murray p++; 29781cb6ddcSMark Murray *p++ = FB64_IV_OK; 29881cb6ddcSMark Murray *p++ = IAC; 29981cb6ddcSMark Murray *p++ = SE; 30081cb6ddcSMark Murray printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 30181cb6ddcSMark Murray net_write(fbp->fb_feed, p - fbp->fb_feed); 30281cb6ddcSMark Murray 30381cb6ddcSMark Murray state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; 30481cb6ddcSMark Murray break; 30581cb6ddcSMark Murray 30681cb6ddcSMark Murray default: 30781cb6ddcSMark Murray if (encrypt_debug_mode) { 30881cb6ddcSMark Murray printf("Unknown option type: %d\r\n", *(data-1)); 30981cb6ddcSMark Murray printd(data, cnt); 31081cb6ddcSMark Murray printf("\r\n"); 31181cb6ddcSMark Murray } 31281cb6ddcSMark Murray /* FALL THROUGH */ 31381cb6ddcSMark Murray failure: 31481cb6ddcSMark Murray /* 31581cb6ddcSMark Murray * We failed. Send an FB64_IV_BAD option 31681cb6ddcSMark Murray * to the other side so it will know that 31781cb6ddcSMark Murray * things failed. 31881cb6ddcSMark Murray */ 31981cb6ddcSMark Murray p = fbp->fb_feed + 3; 32081cb6ddcSMark Murray *p++ = ENCRYPT_REPLY; 32181cb6ddcSMark Murray p++; 32281cb6ddcSMark Murray *p++ = FB64_IV_BAD; 32381cb6ddcSMark Murray *p++ = IAC; 32481cb6ddcSMark Murray *p++ = SE; 32581cb6ddcSMark Murray printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 32681cb6ddcSMark Murray net_write(fbp->fb_feed, p - fbp->fb_feed); 32781cb6ddcSMark Murray 32881cb6ddcSMark Murray break; 32981cb6ddcSMark Murray } 33081cb6ddcSMark Murray return(fbp->state[DIR_DECRYPT-1] = state); 33181cb6ddcSMark Murray } 33281cb6ddcSMark Murray 33381cb6ddcSMark Murray /* 33481cb6ddcSMark Murray * Returns: 33581cb6ddcSMark Murray * -1: some error. Negotiation is done, encryption not ready. 33681cb6ddcSMark Murray * 0: Successful, initial negotiation all done. 33781cb6ddcSMark Murray * 1: successful, negotiation not done yet. 33881cb6ddcSMark Murray */ 33981cb6ddcSMark Murray int 34081cb6ddcSMark Murray cfb64_reply(data, cnt) 34181cb6ddcSMark Murray unsigned char *data; 34281cb6ddcSMark Murray int cnt; 34381cb6ddcSMark Murray { 34481cb6ddcSMark Murray return(fb64_reply(data, cnt, &fb[CFB])); 34581cb6ddcSMark Murray } 34681cb6ddcSMark Murray int 34781cb6ddcSMark Murray ofb64_reply(data, cnt) 34881cb6ddcSMark Murray unsigned char *data; 34981cb6ddcSMark Murray int cnt; 35081cb6ddcSMark Murray { 35181cb6ddcSMark Murray return(fb64_reply(data, cnt, &fb[OFB])); 35281cb6ddcSMark Murray } 35381cb6ddcSMark Murray 35481cb6ddcSMark Murray 35581cb6ddcSMark Murray int 35681cb6ddcSMark Murray fb64_reply(data, cnt, fbp) 35781cb6ddcSMark Murray unsigned char *data; 35881cb6ddcSMark Murray int cnt; 35981cb6ddcSMark Murray struct fb *fbp; 36081cb6ddcSMark Murray { 36181cb6ddcSMark Murray register int state = fbp->state[DIR_ENCRYPT-1]; 36281cb6ddcSMark Murray 36381cb6ddcSMark Murray if (cnt-- < 1) 36481cb6ddcSMark Murray goto failure; 36581cb6ddcSMark Murray 36681cb6ddcSMark Murray switch (*data++) { 36781cb6ddcSMark Murray case FB64_IV_OK: 36881cb6ddcSMark Murray fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 36981cb6ddcSMark Murray if (state == FAILED) 37081cb6ddcSMark Murray state = IN_PROGRESS; 37181cb6ddcSMark Murray state &= ~NO_RECV_IV; 37281cb6ddcSMark Murray encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); 37381cb6ddcSMark Murray break; 37481cb6ddcSMark Murray 37581cb6ddcSMark Murray case FB64_IV_BAD: 37681cb6ddcSMark Murray memset(fbp->temp_feed, 0, sizeof(Block)); 37781cb6ddcSMark Murray fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 37881cb6ddcSMark Murray state = FAILED; 37981cb6ddcSMark Murray break; 38081cb6ddcSMark Murray 38181cb6ddcSMark Murray default: 38281cb6ddcSMark Murray if (encrypt_debug_mode) { 38381cb6ddcSMark Murray printf("Unknown option type: %d\r\n", data[-1]); 38481cb6ddcSMark Murray printd(data, cnt); 38581cb6ddcSMark Murray printf("\r\n"); 38681cb6ddcSMark Murray } 38781cb6ddcSMark Murray /* FALL THROUGH */ 38881cb6ddcSMark Murray failure: 38981cb6ddcSMark Murray state = FAILED; 39081cb6ddcSMark Murray break; 39181cb6ddcSMark Murray } 39281cb6ddcSMark Murray return(fbp->state[DIR_ENCRYPT-1] = state); 39381cb6ddcSMark Murray } 39481cb6ddcSMark Murray 39581cb6ddcSMark Murray void 39681cb6ddcSMark Murray cfb64_session(key, server) 39781cb6ddcSMark Murray Session_Key *key; 39881cb6ddcSMark Murray int server; 39981cb6ddcSMark Murray { 40081cb6ddcSMark Murray fb64_session(key, server, &fb[CFB]); 40181cb6ddcSMark Murray } 40281cb6ddcSMark Murray 40381cb6ddcSMark Murray void 40481cb6ddcSMark Murray ofb64_session(key, server) 40581cb6ddcSMark Murray Session_Key *key; 40681cb6ddcSMark Murray int server; 40781cb6ddcSMark Murray { 40881cb6ddcSMark Murray fb64_session(key, server, &fb[OFB]); 40981cb6ddcSMark Murray } 41081cb6ddcSMark Murray 41181cb6ddcSMark Murray static void 41281cb6ddcSMark Murray fb64_session(key, server, fbp) 41381cb6ddcSMark Murray Session_Key *key; 41481cb6ddcSMark Murray int server; 41581cb6ddcSMark Murray struct fb *fbp; 41681cb6ddcSMark Murray { 41781cb6ddcSMark Murray 41881cb6ddcSMark Murray if (!key || key->type != SK_DES) { 41981cb6ddcSMark Murray if (encrypt_debug_mode) 42081cb6ddcSMark Murray printf("Can't set krbdes's session key (%d != %d)\r\n", 42181cb6ddcSMark Murray key ? key->type : -1, SK_DES); 42281cb6ddcSMark Murray return; 42381cb6ddcSMark Murray } 42481cb6ddcSMark Murray memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); 42581cb6ddcSMark Murray 42681cb6ddcSMark Murray fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); 42781cb6ddcSMark Murray fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); 42881cb6ddcSMark Murray 42981cb6ddcSMark Murray if (fbp->once == 0) { 43004c426ccSMark Murray des_set_random_generator_seed((Block *)fbp->krbdes_key); 43181cb6ddcSMark Murray fbp->once = 1; 43281cb6ddcSMark Murray } 43304c426ccSMark Murray des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); 43481cb6ddcSMark Murray /* 43581cb6ddcSMark Murray * Now look to see if krbdes_start() was was waiting for 43681cb6ddcSMark Murray * the key to show up. If so, go ahead an call it now 43781cb6ddcSMark Murray * that we have the key. 43881cb6ddcSMark Murray */ 43981cb6ddcSMark Murray if (fbp->need_start) { 44081cb6ddcSMark Murray fbp->need_start = 0; 44181cb6ddcSMark Murray fb64_start(fbp, DIR_ENCRYPT, server); 44281cb6ddcSMark Murray } 44381cb6ddcSMark Murray } 44481cb6ddcSMark Murray 44581cb6ddcSMark Murray /* 44681cb6ddcSMark Murray * We only accept a keyid of 0. If we get a keyid of 44781cb6ddcSMark Murray * 0, then mark the state as SUCCESS. 44881cb6ddcSMark Murray */ 44981cb6ddcSMark Murray int 45081cb6ddcSMark Murray cfb64_keyid(dir, kp, lenp) 45181cb6ddcSMark Murray int dir, *lenp; 45281cb6ddcSMark Murray unsigned char *kp; 45381cb6ddcSMark Murray { 45481cb6ddcSMark Murray return(fb64_keyid(dir, kp, lenp, &fb[CFB])); 45581cb6ddcSMark Murray } 45681cb6ddcSMark Murray 45781cb6ddcSMark Murray int 45881cb6ddcSMark Murray ofb64_keyid(dir, kp, lenp) 45981cb6ddcSMark Murray int dir, *lenp; 46081cb6ddcSMark Murray unsigned char *kp; 46181cb6ddcSMark Murray { 46281cb6ddcSMark Murray return(fb64_keyid(dir, kp, lenp, &fb[OFB])); 46381cb6ddcSMark Murray } 46481cb6ddcSMark Murray 46581cb6ddcSMark Murray int 46681cb6ddcSMark Murray fb64_keyid(dir, kp, lenp, fbp) 46781cb6ddcSMark Murray int dir, *lenp; 46881cb6ddcSMark Murray unsigned char *kp; 46981cb6ddcSMark Murray struct fb *fbp; 47081cb6ddcSMark Murray { 47181cb6ddcSMark Murray register int state = fbp->state[dir-1]; 47281cb6ddcSMark Murray 47381cb6ddcSMark Murray if (*lenp != 1 || (*kp != '\0')) { 47481cb6ddcSMark Murray *lenp = 0; 47581cb6ddcSMark Murray return(state); 47681cb6ddcSMark Murray } 47781cb6ddcSMark Murray 47881cb6ddcSMark Murray if (state == FAILED) 47981cb6ddcSMark Murray state = IN_PROGRESS; 48081cb6ddcSMark Murray 48181cb6ddcSMark Murray state &= ~NO_KEYID; 48281cb6ddcSMark Murray 48381cb6ddcSMark Murray return(fbp->state[dir-1] = state); 48481cb6ddcSMark Murray } 48581cb6ddcSMark Murray 48681cb6ddcSMark Murray void 48781cb6ddcSMark Murray fb64_printsub(data, cnt, buf, buflen, type) 48881cb6ddcSMark Murray unsigned char *data, *buf, *type; 48981cb6ddcSMark Murray int cnt, buflen; 49081cb6ddcSMark Murray { 49181cb6ddcSMark Murray char lbuf[32]; 49281cb6ddcSMark Murray register int i; 49381cb6ddcSMark Murray char *cp; 49481cb6ddcSMark Murray 49581cb6ddcSMark Murray buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 49681cb6ddcSMark Murray buflen -= 1; 49781cb6ddcSMark Murray 49881cb6ddcSMark Murray switch(data[2]) { 49981cb6ddcSMark Murray case FB64_IV: 50081cb6ddcSMark Murray sprintf(lbuf, "%s_IV", type); 50181cb6ddcSMark Murray cp = lbuf; 50281cb6ddcSMark Murray goto common; 50381cb6ddcSMark Murray 50481cb6ddcSMark Murray case FB64_IV_OK: 50581cb6ddcSMark Murray sprintf(lbuf, "%s_IV_OK", type); 50681cb6ddcSMark Murray cp = lbuf; 50781cb6ddcSMark Murray goto common; 50881cb6ddcSMark Murray 50981cb6ddcSMark Murray case FB64_IV_BAD: 51081cb6ddcSMark Murray sprintf(lbuf, "%s_IV_BAD", type); 51181cb6ddcSMark Murray cp = lbuf; 51281cb6ddcSMark Murray goto common; 51381cb6ddcSMark Murray 51481cb6ddcSMark Murray default: 51581cb6ddcSMark Murray sprintf(lbuf, " %d (unknown)", data[2]); 51681cb6ddcSMark Murray cp = lbuf; 51781cb6ddcSMark Murray common: 51881cb6ddcSMark Murray for (; (buflen > 0) && (*buf = *cp++); buf++) 51981cb6ddcSMark Murray buflen--; 52081cb6ddcSMark Murray for (i = 3; i < cnt; i++) { 52181cb6ddcSMark Murray sprintf(lbuf, " %d", data[i]); 52281cb6ddcSMark Murray for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) 52381cb6ddcSMark Murray buflen--; 52481cb6ddcSMark Murray } 52581cb6ddcSMark Murray break; 52681cb6ddcSMark Murray } 52781cb6ddcSMark Murray } 52881cb6ddcSMark Murray 52981cb6ddcSMark Murray void 53081cb6ddcSMark Murray cfb64_printsub(data, cnt, buf, buflen) 53181cb6ddcSMark Murray unsigned char *data, *buf; 53281cb6ddcSMark Murray int cnt, buflen; 53381cb6ddcSMark Murray { 53481cb6ddcSMark Murray fb64_printsub(data, cnt, buf, buflen, "CFB64"); 53581cb6ddcSMark Murray } 53681cb6ddcSMark Murray 53781cb6ddcSMark Murray void 53881cb6ddcSMark Murray ofb64_printsub(data, cnt, buf, buflen) 53981cb6ddcSMark Murray unsigned char *data, *buf; 54081cb6ddcSMark Murray int cnt, buflen; 54181cb6ddcSMark Murray { 54281cb6ddcSMark Murray fb64_printsub(data, cnt, buf, buflen, "OFB64"); 54381cb6ddcSMark Murray } 54481cb6ddcSMark Murray 54581cb6ddcSMark Murray void 54681cb6ddcSMark Murray fb64_stream_iv(seed, stp) 54781cb6ddcSMark Murray Block seed; 54881cb6ddcSMark Murray register struct stinfo *stp; 54981cb6ddcSMark Murray { 55081cb6ddcSMark Murray 55181cb6ddcSMark Murray memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); 55281cb6ddcSMark Murray memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); 55381cb6ddcSMark Murray 55404c426ccSMark Murray des_key_sched((Block *)stp->str_ikey, stp->str_sched); 55581cb6ddcSMark Murray 55681cb6ddcSMark Murray stp->str_index = sizeof(Block); 55781cb6ddcSMark Murray } 55881cb6ddcSMark Murray 55981cb6ddcSMark Murray void 56081cb6ddcSMark Murray fb64_stream_key(key, stp) 56181cb6ddcSMark Murray Block key; 56281cb6ddcSMark Murray register struct stinfo *stp; 56381cb6ddcSMark Murray { 56481cb6ddcSMark Murray memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); 56504c426ccSMark Murray des_key_sched((Block *)key, stp->str_sched); 56681cb6ddcSMark Murray 56781cb6ddcSMark Murray memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); 56881cb6ddcSMark Murray 56981cb6ddcSMark Murray stp->str_index = sizeof(Block); 57081cb6ddcSMark Murray } 57181cb6ddcSMark Murray 57281cb6ddcSMark Murray /* 57381cb6ddcSMark Murray * DES 64 bit Cipher Feedback 57481cb6ddcSMark Murray * 57581cb6ddcSMark Murray * key --->+-----+ 57681cb6ddcSMark Murray * +->| DES |--+ 57781cb6ddcSMark Murray * | +-----+ | 57881cb6ddcSMark Murray * | v 57981cb6ddcSMark Murray * INPUT --(--------->(+)+---> DATA 58081cb6ddcSMark Murray * | | 58181cb6ddcSMark Murray * +-------------+ 58281cb6ddcSMark Murray * 58381cb6ddcSMark Murray * 58481cb6ddcSMark Murray * Given: 58581cb6ddcSMark Murray * iV: Initial vector, 64 bits (8 bytes) long. 58681cb6ddcSMark Murray * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 58781cb6ddcSMark Murray * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 58881cb6ddcSMark Murray * 58981cb6ddcSMark Murray * V0 = DES(iV, key) 59081cb6ddcSMark Murray * On = Dn ^ Vn 59181cb6ddcSMark Murray * V(n+1) = DES(On, key) 59281cb6ddcSMark Murray */ 59381cb6ddcSMark Murray 59481cb6ddcSMark Murray void 59581cb6ddcSMark Murray cfb64_encrypt(s, c) 59681cb6ddcSMark Murray register unsigned char *s; 59781cb6ddcSMark Murray int c; 59881cb6ddcSMark Murray { 59981cb6ddcSMark Murray register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; 60081cb6ddcSMark Murray register int index; 60181cb6ddcSMark Murray 60281cb6ddcSMark Murray index = stp->str_index; 60381cb6ddcSMark Murray while (c-- > 0) { 60481cb6ddcSMark Murray if (index == sizeof(Block)) { 60581cb6ddcSMark Murray Block b; 60604c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 60781cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 60881cb6ddcSMark Murray index = 0; 60981cb6ddcSMark Murray } 61081cb6ddcSMark Murray 61181cb6ddcSMark Murray /* On encryption, we store (feed ^ data) which is cypher */ 61281cb6ddcSMark Murray *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); 61381cb6ddcSMark Murray s++; 61481cb6ddcSMark Murray index++; 61581cb6ddcSMark Murray } 61681cb6ddcSMark Murray stp->str_index = index; 61781cb6ddcSMark Murray } 61881cb6ddcSMark Murray 61981cb6ddcSMark Murray int 62081cb6ddcSMark Murray cfb64_decrypt(data) 62181cb6ddcSMark Murray int data; 62281cb6ddcSMark Murray { 62381cb6ddcSMark Murray register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 62481cb6ddcSMark Murray int index; 62581cb6ddcSMark Murray 62681cb6ddcSMark Murray if (data == -1) { 62781cb6ddcSMark Murray /* 62881cb6ddcSMark Murray * Back up one byte. It is assumed that we will 62981cb6ddcSMark Murray * never back up more than one byte. If we do, this 63081cb6ddcSMark Murray * may or may not work. 63181cb6ddcSMark Murray */ 63281cb6ddcSMark Murray if (stp->str_index) 63381cb6ddcSMark Murray --stp->str_index; 63481cb6ddcSMark Murray return(0); 63581cb6ddcSMark Murray } 63681cb6ddcSMark Murray 63781cb6ddcSMark Murray index = stp->str_index++; 63881cb6ddcSMark Murray if (index == sizeof(Block)) { 63981cb6ddcSMark Murray Block b; 64004c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 64181cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 64281cb6ddcSMark Murray stp->str_index = 1; /* Next time will be 1 */ 64381cb6ddcSMark Murray index = 0; /* But now use 0 */ 64481cb6ddcSMark Murray } 64581cb6ddcSMark Murray 64681cb6ddcSMark Murray /* On decryption we store (data) which is cypher. */ 64781cb6ddcSMark Murray stp->str_output[index] = data; 64881cb6ddcSMark Murray return(data ^ stp->str_feed[index]); 64981cb6ddcSMark Murray } 65081cb6ddcSMark Murray 65181cb6ddcSMark Murray /* 65281cb6ddcSMark Murray * DES 64 bit Output Feedback 65381cb6ddcSMark Murray * 65481cb6ddcSMark Murray * key --->+-----+ 65581cb6ddcSMark Murray * +->| DES |--+ 65681cb6ddcSMark Murray * | +-----+ | 65781cb6ddcSMark Murray * +-----------+ 65881cb6ddcSMark Murray * v 65981cb6ddcSMark Murray * INPUT -------->(+) ----> DATA 66081cb6ddcSMark Murray * 66181cb6ddcSMark Murray * Given: 66281cb6ddcSMark Murray * iV: Initial vector, 64 bits (8 bytes) long. 66381cb6ddcSMark Murray * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 66481cb6ddcSMark Murray * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 66581cb6ddcSMark Murray * 66681cb6ddcSMark Murray * V0 = DES(iV, key) 66781cb6ddcSMark Murray * V(n+1) = DES(Vn, key) 66881cb6ddcSMark Murray * On = Dn ^ Vn 66981cb6ddcSMark Murray */ 67081cb6ddcSMark Murray void 67181cb6ddcSMark Murray ofb64_encrypt(s, c) 67281cb6ddcSMark Murray register unsigned char *s; 67381cb6ddcSMark Murray int c; 67481cb6ddcSMark Murray { 67581cb6ddcSMark Murray register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; 67681cb6ddcSMark Murray register int index; 67781cb6ddcSMark Murray 67881cb6ddcSMark Murray index = stp->str_index; 67981cb6ddcSMark Murray while (c-- > 0) { 68081cb6ddcSMark Murray if (index == sizeof(Block)) { 68181cb6ddcSMark Murray Block b; 68204c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 68381cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 68481cb6ddcSMark Murray index = 0; 68581cb6ddcSMark Murray } 68681cb6ddcSMark Murray *s++ ^= stp->str_feed[index]; 68781cb6ddcSMark Murray index++; 68881cb6ddcSMark Murray } 68981cb6ddcSMark Murray stp->str_index = index; 69081cb6ddcSMark Murray } 69181cb6ddcSMark Murray 69281cb6ddcSMark Murray int 69381cb6ddcSMark Murray ofb64_decrypt(data) 69481cb6ddcSMark Murray int data; 69581cb6ddcSMark Murray { 69681cb6ddcSMark Murray register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 69781cb6ddcSMark Murray int index; 69881cb6ddcSMark Murray 69981cb6ddcSMark Murray if (data == -1) { 70081cb6ddcSMark Murray /* 70181cb6ddcSMark Murray * Back up one byte. It is assumed that we will 70281cb6ddcSMark Murray * never back up more than one byte. If we do, this 70381cb6ddcSMark Murray * may or may not work. 70481cb6ddcSMark Murray */ 70581cb6ddcSMark Murray if (stp->str_index) 70681cb6ddcSMark Murray --stp->str_index; 70781cb6ddcSMark Murray return(0); 70881cb6ddcSMark Murray } 70981cb6ddcSMark Murray 71081cb6ddcSMark Murray index = stp->str_index++; 71181cb6ddcSMark Murray if (index == sizeof(Block)) { 71281cb6ddcSMark Murray Block b; 71304c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 71481cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 71581cb6ddcSMark Murray stp->str_index = 1; /* Next time will be 1 */ 71681cb6ddcSMark Murray index = 0; /* But now use 0 */ 71781cb6ddcSMark Murray } 71881cb6ddcSMark Murray 71981cb6ddcSMark Murray return(data ^ stp->str_feed[index]); 72081cb6ddcSMark Murray } 72181cb6ddcSMark Murray # endif /* DES_ENCRYPTION */ 72281cb6ddcSMark Murray # endif /* AUTHENTICATION */ 72381cb6ddcSMark Murray #endif /* ENCRYPTION */ 724