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. 3281cb6ddcSMark Murray */ 3381cb6ddcSMark Murray 3477b7cdf1SDavid E. O'Brien #if 0 3581cb6ddcSMark Murray #ifndef lint 3604c426ccSMark Murray static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; 3781cb6ddcSMark Murray #endif /* not lint */ 3877b7cdf1SDavid E. O'Brien #endif 3977b7cdf1SDavid E. O'Brien #include <sys/cdefs.h> 4077b7cdf1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 4181cb6ddcSMark Murray 4281cb6ddcSMark Murray #ifdef ENCRYPTION 4381cb6ddcSMark Murray # ifdef AUTHENTICATION 4481cb6ddcSMark Murray #include <arpa/telnet.h> 45bf4f84d4SMark Murray #include <openssl/des.h> 468fa113e5SMark Murray #include <stdio.h> 478fa113e5SMark Murray #include <stdlib.h> 4804c426ccSMark Murray #include <string.h> 498fa113e5SMark Murray 5081cb6ddcSMark Murray #include "encrypt.h" 5181cb6ddcSMark Murray #include "key-proto.h" 5281cb6ddcSMark Murray #include "misc-proto.h" 5381cb6ddcSMark Murray 5421f083c0SMark Murray extern int encrypt_debug_mode; 5581cb6ddcSMark Murray 5681cb6ddcSMark Murray #define CFB 0 5781cb6ddcSMark Murray #define OFB 1 5881cb6ddcSMark Murray 5981cb6ddcSMark Murray #define NO_SEND_IV 1 6081cb6ddcSMark Murray #define NO_RECV_IV 2 6181cb6ddcSMark Murray #define NO_KEYID 4 6281cb6ddcSMark Murray #define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) 6381cb6ddcSMark Murray #define SUCCESS 0 6481cb6ddcSMark Murray #define FAILED -1 6581cb6ddcSMark Murray 6681cb6ddcSMark Murray 6781cb6ddcSMark Murray struct fb { 6881cb6ddcSMark Murray Block krbdes_key; 6981cb6ddcSMark Murray Schedule krbdes_sched; 7081cb6ddcSMark Murray Block temp_feed; 7181cb6ddcSMark Murray unsigned char fb_feed[64]; 7281cb6ddcSMark Murray int need_start; 7381cb6ddcSMark Murray int state[2]; 7481cb6ddcSMark Murray int keyid[2]; 7581cb6ddcSMark Murray struct stinfo { 7681cb6ddcSMark Murray Block str_output; 7781cb6ddcSMark Murray Block str_feed; 7881cb6ddcSMark Murray Block str_iv; 7981cb6ddcSMark Murray Block str_ikey; 8081cb6ddcSMark Murray Schedule str_sched; 8181cb6ddcSMark Murray int str_index; 8281cb6ddcSMark Murray int str_flagshift; 8381cb6ddcSMark Murray } streams[2]; 8481cb6ddcSMark Murray }; 8581cb6ddcSMark Murray 8681cb6ddcSMark Murray static struct fb fb[2]; 8781cb6ddcSMark Murray 8881cb6ddcSMark Murray struct keyidlist { 898fa113e5SMark Murray const char *keyid; 9081cb6ddcSMark Murray int keyidlen; 9181cb6ddcSMark Murray char *key; 9281cb6ddcSMark Murray int keylen; 9381cb6ddcSMark Murray int flags; 9481cb6ddcSMark Murray } keyidlist [] = { 9581cb6ddcSMark Murray { "\0", 1, 0, 0, 0 }, /* default key of zero */ 9681cb6ddcSMark Murray { 0, 0, 0, 0, 0 } 9781cb6ddcSMark Murray }; 9881cb6ddcSMark Murray 9981cb6ddcSMark Murray #define KEYFLAG_MASK 03 10081cb6ddcSMark Murray 10181cb6ddcSMark Murray #define KEYFLAG_NOINIT 00 10281cb6ddcSMark Murray #define KEYFLAG_INIT 01 10381cb6ddcSMark Murray #define KEYFLAG_OK 02 10481cb6ddcSMark Murray #define KEYFLAG_BAD 03 10581cb6ddcSMark Murray 10681cb6ddcSMark Murray #define KEYFLAG_SHIFT 2 10781cb6ddcSMark Murray 10881cb6ddcSMark Murray #define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) 10981cb6ddcSMark Murray 11081cb6ddcSMark Murray #define FB64_IV 1 11181cb6ddcSMark Murray #define FB64_IV_OK 2 11281cb6ddcSMark Murray #define FB64_IV_BAD 3 11381cb6ddcSMark Murray 11481cb6ddcSMark Murray 1153138440aSMark Murray void fb64_stream_iv(Block, struct stinfo *); 1163138440aSMark Murray void fb64_init(struct fb *); 1173138440aSMark Murray static int fb64_start(struct fb *, int, int); 1183138440aSMark Murray int fb64_is(unsigned char *, int, struct fb *); 1193138440aSMark Murray int fb64_reply(unsigned char *, int, struct fb *); 1203138440aSMark Murray static void fb64_session(Session_Key *, int, struct fb *); 1213138440aSMark Murray void fb64_stream_key(Block, struct stinfo *); 1223138440aSMark Murray int fb64_keyid(int, unsigned char *, int *, struct fb *); 12381cb6ddcSMark Murray 12481cb6ddcSMark Murray void 1258fa113e5SMark Murray cfb64_init(int server __unused) 12681cb6ddcSMark Murray { 12781cb6ddcSMark Murray fb64_init(&fb[CFB]); 12881cb6ddcSMark Murray fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; 12981cb6ddcSMark Murray fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); 13081cb6ddcSMark Murray fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); 13181cb6ddcSMark Murray } 13281cb6ddcSMark Murray 13381cb6ddcSMark Murray void 1348fa113e5SMark Murray ofb64_init(int server __unused) 13581cb6ddcSMark Murray { 13681cb6ddcSMark Murray fb64_init(&fb[OFB]); 13781cb6ddcSMark Murray fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; 13881cb6ddcSMark Murray fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); 13981cb6ddcSMark Murray fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); 14081cb6ddcSMark Murray } 14181cb6ddcSMark Murray 14281cb6ddcSMark Murray void 1438fa113e5SMark Murray fb64_init(struct fb *fbp) 14481cb6ddcSMark Murray { 14581cb6ddcSMark Murray memset((void *)fbp, 0, sizeof(*fbp)); 14681cb6ddcSMark Murray fbp->state[0] = fbp->state[1] = FAILED; 14781cb6ddcSMark Murray fbp->fb_feed[0] = IAC; 14881cb6ddcSMark Murray fbp->fb_feed[1] = SB; 14981cb6ddcSMark Murray fbp->fb_feed[2] = TELOPT_ENCRYPT; 15081cb6ddcSMark Murray fbp->fb_feed[3] = ENCRYPT_IS; 15181cb6ddcSMark Murray } 15281cb6ddcSMark Murray 15381cb6ddcSMark Murray /* 15481cb6ddcSMark Murray * Returns: 15581cb6ddcSMark Murray * -1: some error. Negotiation is done, encryption not ready. 15681cb6ddcSMark Murray * 0: Successful, initial negotiation all done. 15781cb6ddcSMark Murray * 1: successful, negotiation not done yet. 15881cb6ddcSMark Murray * 2: Not yet. Other things (like getting the key from 15981cb6ddcSMark Murray * Kerberos) have to happen before we can continue. 16081cb6ddcSMark Murray */ 16181cb6ddcSMark Murray int 1628fa113e5SMark Murray cfb64_start(int dir, int server) 16381cb6ddcSMark Murray { 16481cb6ddcSMark Murray return(fb64_start(&fb[CFB], dir, server)); 16581cb6ddcSMark Murray } 1668fa113e5SMark Murray 16781cb6ddcSMark Murray int 1688fa113e5SMark Murray ofb64_start(int dir, int server) 16981cb6ddcSMark Murray { 17081cb6ddcSMark Murray return(fb64_start(&fb[OFB], dir, server)); 17181cb6ddcSMark Murray } 17281cb6ddcSMark Murray 17381cb6ddcSMark Murray static int 1748fa113e5SMark Murray fb64_start(struct fb *fbp, int dir, int server __unused) 17581cb6ddcSMark Murray { 1768fa113e5SMark Murray size_t x; 17781cb6ddcSMark Murray unsigned char *p; 1788fa113e5SMark Murray int state; 17981cb6ddcSMark Murray 18081cb6ddcSMark Murray switch (dir) { 18181cb6ddcSMark Murray case DIR_DECRYPT: 18281cb6ddcSMark Murray /* 18381cb6ddcSMark Murray * This is simply a request to have the other side 18481cb6ddcSMark Murray * start output (our input). He will negotiate an 18581cb6ddcSMark Murray * IV so we need not look for it. 18681cb6ddcSMark Murray */ 18781cb6ddcSMark Murray state = fbp->state[dir-1]; 18881cb6ddcSMark Murray if (state == FAILED) 18981cb6ddcSMark Murray state = IN_PROGRESS; 19081cb6ddcSMark Murray break; 19181cb6ddcSMark Murray 19281cb6ddcSMark Murray case DIR_ENCRYPT: 19381cb6ddcSMark Murray state = fbp->state[dir-1]; 19481cb6ddcSMark Murray if (state == FAILED) 19581cb6ddcSMark Murray state = IN_PROGRESS; 19681cb6ddcSMark Murray else if ((state & NO_SEND_IV) == 0) 19781cb6ddcSMark Murray break; 19881cb6ddcSMark Murray 19981cb6ddcSMark Murray if (!VALIDKEY(fbp->krbdes_key)) { 20081cb6ddcSMark Murray fbp->need_start = 1; 20181cb6ddcSMark Murray break; 20281cb6ddcSMark Murray } 20381cb6ddcSMark Murray state &= ~NO_SEND_IV; 20481cb6ddcSMark Murray state |= NO_RECV_IV; 20581cb6ddcSMark Murray if (encrypt_debug_mode) 20681cb6ddcSMark Murray printf("Creating new feed\r\n"); 20781cb6ddcSMark Murray /* 20881cb6ddcSMark Murray * Create a random feed and send it over. 20981cb6ddcSMark Murray */ 2104b2eaea4SJacques Vidrine des_random_key((Block *)fbp->temp_feed); 21104c426ccSMark Murray des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, 21281cb6ddcSMark Murray fbp->krbdes_sched, 1); 21381cb6ddcSMark Murray p = fbp->fb_feed + 3; 21481cb6ddcSMark Murray *p++ = ENCRYPT_IS; 21581cb6ddcSMark Murray p++; 21681cb6ddcSMark Murray *p++ = FB64_IV; 21781cb6ddcSMark Murray for (x = 0; x < sizeof(Block); ++x) { 21881cb6ddcSMark Murray if ((*p++ = fbp->temp_feed[x]) == IAC) 21981cb6ddcSMark Murray *p++ = IAC; 22081cb6ddcSMark Murray } 22181cb6ddcSMark Murray *p++ = IAC; 22281cb6ddcSMark Murray *p++ = SE; 22381cb6ddcSMark Murray printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 22481cb6ddcSMark Murray net_write(fbp->fb_feed, p - fbp->fb_feed); 22581cb6ddcSMark Murray break; 22681cb6ddcSMark Murray default: 22781cb6ddcSMark Murray return(FAILED); 22881cb6ddcSMark Murray } 22981cb6ddcSMark Murray return(fbp->state[dir-1] = state); 23081cb6ddcSMark Murray } 23181cb6ddcSMark Murray 23281cb6ddcSMark Murray /* 23381cb6ddcSMark Murray * Returns: 23481cb6ddcSMark Murray * -1: some error. Negotiation is done, encryption not ready. 23581cb6ddcSMark Murray * 0: Successful, initial negotiation all done. 23681cb6ddcSMark Murray * 1: successful, negotiation not done yet. 23781cb6ddcSMark Murray */ 23881cb6ddcSMark Murray int 2398fa113e5SMark Murray cfb64_is(unsigned char *data, int cnt) 24081cb6ddcSMark Murray { 24181cb6ddcSMark Murray return(fb64_is(data, cnt, &fb[CFB])); 24281cb6ddcSMark Murray } 2438fa113e5SMark Murray 24481cb6ddcSMark Murray int 2458fa113e5SMark Murray ofb64_is(unsigned char *data, int cnt) 24681cb6ddcSMark Murray { 24781cb6ddcSMark Murray return(fb64_is(data, cnt, &fb[OFB])); 24881cb6ddcSMark Murray } 24981cb6ddcSMark Murray 25081cb6ddcSMark Murray int 2518fa113e5SMark Murray fb64_is(unsigned char *data, int cnt, struct fb *fbp) 25281cb6ddcSMark Murray { 25381cb6ddcSMark Murray unsigned char *p; 2548fa113e5SMark Murray int state = fbp->state[DIR_DECRYPT-1]; 25581cb6ddcSMark Murray 25681cb6ddcSMark Murray if (cnt-- < 1) 25781cb6ddcSMark Murray goto failure; 25881cb6ddcSMark Murray 25981cb6ddcSMark Murray switch (*data++) { 26081cb6ddcSMark Murray case FB64_IV: 26181cb6ddcSMark Murray if (cnt != sizeof(Block)) { 26281cb6ddcSMark Murray if (encrypt_debug_mode) 26381cb6ddcSMark Murray printf("CFB64: initial vector failed on size\r\n"); 26481cb6ddcSMark Murray state = FAILED; 26581cb6ddcSMark Murray goto failure; 26681cb6ddcSMark Murray } 26781cb6ddcSMark Murray 26881cb6ddcSMark Murray if (encrypt_debug_mode) 26981cb6ddcSMark Murray printf("CFB64: initial vector received\r\n"); 27081cb6ddcSMark Murray 27181cb6ddcSMark Murray if (encrypt_debug_mode) 27281cb6ddcSMark Murray printf("Initializing Decrypt stream\r\n"); 27381cb6ddcSMark Murray 27481cb6ddcSMark Murray fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); 27581cb6ddcSMark Murray 27681cb6ddcSMark Murray p = fbp->fb_feed + 3; 27781cb6ddcSMark Murray *p++ = ENCRYPT_REPLY; 27881cb6ddcSMark Murray p++; 27981cb6ddcSMark Murray *p++ = FB64_IV_OK; 28081cb6ddcSMark Murray *p++ = IAC; 28181cb6ddcSMark Murray *p++ = SE; 28281cb6ddcSMark Murray printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 28381cb6ddcSMark Murray net_write(fbp->fb_feed, p - fbp->fb_feed); 28481cb6ddcSMark Murray 28581cb6ddcSMark Murray state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; 28681cb6ddcSMark Murray break; 28781cb6ddcSMark Murray 28881cb6ddcSMark Murray default: 28981cb6ddcSMark Murray if (encrypt_debug_mode) { 29081cb6ddcSMark Murray printf("Unknown option type: %d\r\n", *(data-1)); 29181cb6ddcSMark Murray printd(data, cnt); 29281cb6ddcSMark Murray printf("\r\n"); 29381cb6ddcSMark Murray } 29481cb6ddcSMark Murray /* FALL THROUGH */ 29581cb6ddcSMark Murray failure: 29681cb6ddcSMark Murray /* 29781cb6ddcSMark Murray * We failed. Send an FB64_IV_BAD option 29881cb6ddcSMark Murray * to the other side so it will know that 29981cb6ddcSMark Murray * things failed. 30081cb6ddcSMark Murray */ 30181cb6ddcSMark Murray p = fbp->fb_feed + 3; 30281cb6ddcSMark Murray *p++ = ENCRYPT_REPLY; 30381cb6ddcSMark Murray p++; 30481cb6ddcSMark Murray *p++ = FB64_IV_BAD; 30581cb6ddcSMark Murray *p++ = IAC; 30681cb6ddcSMark Murray *p++ = SE; 30781cb6ddcSMark Murray printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 30881cb6ddcSMark Murray net_write(fbp->fb_feed, p - fbp->fb_feed); 30981cb6ddcSMark Murray 31081cb6ddcSMark Murray break; 31181cb6ddcSMark Murray } 31281cb6ddcSMark Murray return(fbp->state[DIR_DECRYPT-1] = state); 31381cb6ddcSMark Murray } 31481cb6ddcSMark Murray 31581cb6ddcSMark Murray /* 31681cb6ddcSMark Murray * Returns: 31781cb6ddcSMark Murray * -1: some error. Negotiation is done, encryption not ready. 31881cb6ddcSMark Murray * 0: Successful, initial negotiation all done. 31981cb6ddcSMark Murray * 1: successful, negotiation not done yet. 32081cb6ddcSMark Murray */ 32181cb6ddcSMark Murray int 3228fa113e5SMark Murray cfb64_reply(unsigned char *data, int cnt) 32381cb6ddcSMark Murray { 32481cb6ddcSMark Murray return(fb64_reply(data, cnt, &fb[CFB])); 32581cb6ddcSMark Murray } 3268fa113e5SMark Murray 32781cb6ddcSMark Murray int 3288fa113e5SMark Murray ofb64_reply(unsigned char *data, int cnt) 32981cb6ddcSMark Murray { 33081cb6ddcSMark Murray return(fb64_reply(data, cnt, &fb[OFB])); 33181cb6ddcSMark Murray } 33281cb6ddcSMark Murray 33381cb6ddcSMark Murray int 3348fa113e5SMark Murray fb64_reply(unsigned char *data, int cnt, struct fb *fbp) 33581cb6ddcSMark Murray { 3368fa113e5SMark Murray int state = fbp->state[DIR_ENCRYPT-1]; 33781cb6ddcSMark Murray 33881cb6ddcSMark Murray if (cnt-- < 1) 33981cb6ddcSMark Murray goto failure; 34081cb6ddcSMark Murray 34181cb6ddcSMark Murray switch (*data++) { 34281cb6ddcSMark Murray case FB64_IV_OK: 34381cb6ddcSMark Murray fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 34481cb6ddcSMark Murray if (state == FAILED) 34581cb6ddcSMark Murray state = IN_PROGRESS; 34681cb6ddcSMark Murray state &= ~NO_RECV_IV; 3478fa113e5SMark Murray encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1); 34881cb6ddcSMark Murray break; 34981cb6ddcSMark Murray 35081cb6ddcSMark Murray case FB64_IV_BAD: 35181cb6ddcSMark Murray memset(fbp->temp_feed, 0, sizeof(Block)); 35281cb6ddcSMark Murray fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 35381cb6ddcSMark Murray state = FAILED; 35481cb6ddcSMark Murray break; 35581cb6ddcSMark Murray 35681cb6ddcSMark Murray default: 35781cb6ddcSMark Murray if (encrypt_debug_mode) { 35881cb6ddcSMark Murray printf("Unknown option type: %d\r\n", data[-1]); 35981cb6ddcSMark Murray printd(data, cnt); 36081cb6ddcSMark Murray printf("\r\n"); 36181cb6ddcSMark Murray } 36281cb6ddcSMark Murray /* FALL THROUGH */ 36381cb6ddcSMark Murray failure: 36481cb6ddcSMark Murray state = FAILED; 36581cb6ddcSMark Murray break; 36681cb6ddcSMark Murray } 36781cb6ddcSMark Murray return(fbp->state[DIR_ENCRYPT-1] = state); 36881cb6ddcSMark Murray } 36981cb6ddcSMark Murray 37081cb6ddcSMark Murray void 3718fa113e5SMark Murray cfb64_session(Session_Key *key, int server) 37281cb6ddcSMark Murray { 37381cb6ddcSMark Murray fb64_session(key, server, &fb[CFB]); 37481cb6ddcSMark Murray } 37581cb6ddcSMark Murray 37681cb6ddcSMark Murray void 3778fa113e5SMark Murray ofb64_session(Session_Key *key, int server) 37881cb6ddcSMark Murray { 37981cb6ddcSMark Murray fb64_session(key, server, &fb[OFB]); 38081cb6ddcSMark Murray } 38181cb6ddcSMark Murray 38281cb6ddcSMark Murray static void 3838fa113e5SMark Murray fb64_session(Session_Key *key, int server, struct fb *fbp) 38481cb6ddcSMark Murray { 38581cb6ddcSMark Murray if (!key || key->type != SK_DES) { 38681cb6ddcSMark Murray if (encrypt_debug_mode) 38781cb6ddcSMark Murray printf("Can't set krbdes's session key (%d != %d)\r\n", 38881cb6ddcSMark Murray key ? key->type : -1, SK_DES); 38981cb6ddcSMark Murray return; 39081cb6ddcSMark Murray } 39181cb6ddcSMark Murray memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); 39281cb6ddcSMark Murray 39381cb6ddcSMark Murray fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); 39481cb6ddcSMark Murray fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); 39581cb6ddcSMark Murray 39604c426ccSMark Murray des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); 39781cb6ddcSMark Murray /* 39881cb6ddcSMark Murray * Now look to see if krbdes_start() was was waiting for 39981cb6ddcSMark Murray * the key to show up. If so, go ahead an call it now 40081cb6ddcSMark Murray * that we have the key. 40181cb6ddcSMark Murray */ 40281cb6ddcSMark Murray if (fbp->need_start) { 40381cb6ddcSMark Murray fbp->need_start = 0; 40481cb6ddcSMark Murray fb64_start(fbp, DIR_ENCRYPT, server); 40581cb6ddcSMark Murray } 40681cb6ddcSMark Murray } 40781cb6ddcSMark Murray 40881cb6ddcSMark Murray /* 40981cb6ddcSMark Murray * We only accept a keyid of 0. If we get a keyid of 41081cb6ddcSMark Murray * 0, then mark the state as SUCCESS. 41181cb6ddcSMark Murray */ 41281cb6ddcSMark Murray int 4138fa113e5SMark Murray cfb64_keyid(int dir, unsigned char *kp, int *lenp) 41481cb6ddcSMark Murray { 41581cb6ddcSMark Murray return(fb64_keyid(dir, kp, lenp, &fb[CFB])); 41681cb6ddcSMark Murray } 41781cb6ddcSMark Murray 41881cb6ddcSMark Murray int 4198fa113e5SMark Murray ofb64_keyid(int dir, unsigned char *kp, int *lenp) 42081cb6ddcSMark Murray { 42181cb6ddcSMark Murray return(fb64_keyid(dir, kp, lenp, &fb[OFB])); 42281cb6ddcSMark Murray } 42381cb6ddcSMark Murray 42481cb6ddcSMark Murray int 4258fa113e5SMark Murray fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp) 42681cb6ddcSMark Murray { 4278fa113e5SMark Murray int state = fbp->state[dir-1]; 42881cb6ddcSMark Murray 42981cb6ddcSMark Murray if (*lenp != 1 || (*kp != '\0')) { 43081cb6ddcSMark Murray *lenp = 0; 43181cb6ddcSMark Murray return(state); 43281cb6ddcSMark Murray } 43381cb6ddcSMark Murray 43481cb6ddcSMark Murray if (state == FAILED) 43581cb6ddcSMark Murray state = IN_PROGRESS; 43681cb6ddcSMark Murray 43781cb6ddcSMark Murray state &= ~NO_KEYID; 43881cb6ddcSMark Murray 43981cb6ddcSMark Murray return(fbp->state[dir-1] = state); 44081cb6ddcSMark Murray } 44181cb6ddcSMark Murray 44281cb6ddcSMark Murray void 4438fa113e5SMark Murray fb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type) 44481cb6ddcSMark Murray { 44581cb6ddcSMark Murray char lbuf[32]; 4468fa113e5SMark Murray int i; 44781cb6ddcSMark Murray char *cp; 44881cb6ddcSMark Murray 44981cb6ddcSMark Murray buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 45081cb6ddcSMark Murray buflen -= 1; 45181cb6ddcSMark Murray 45281cb6ddcSMark Murray switch(data[2]) { 45381cb6ddcSMark Murray case FB64_IV: 45481cb6ddcSMark Murray sprintf(lbuf, "%s_IV", type); 45581cb6ddcSMark Murray cp = lbuf; 45681cb6ddcSMark Murray goto common; 45781cb6ddcSMark Murray 45881cb6ddcSMark Murray case FB64_IV_OK: 45981cb6ddcSMark Murray sprintf(lbuf, "%s_IV_OK", type); 46081cb6ddcSMark Murray cp = lbuf; 46181cb6ddcSMark Murray goto common; 46281cb6ddcSMark Murray 46381cb6ddcSMark Murray case FB64_IV_BAD: 46481cb6ddcSMark Murray sprintf(lbuf, "%s_IV_BAD", type); 46581cb6ddcSMark Murray cp = lbuf; 46681cb6ddcSMark Murray goto common; 46781cb6ddcSMark Murray 46881cb6ddcSMark Murray default: 46981cb6ddcSMark Murray sprintf(lbuf, " %d (unknown)", data[2]); 47081cb6ddcSMark Murray cp = lbuf; 47181cb6ddcSMark Murray common: 47281cb6ddcSMark Murray for (; (buflen > 0) && (*buf = *cp++); buf++) 47381cb6ddcSMark Murray buflen--; 47481cb6ddcSMark Murray for (i = 3; i < cnt; i++) { 47581cb6ddcSMark Murray sprintf(lbuf, " %d", data[i]); 47681cb6ddcSMark Murray for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) 47781cb6ddcSMark Murray buflen--; 47881cb6ddcSMark Murray } 47981cb6ddcSMark Murray break; 48081cb6ddcSMark Murray } 48181cb6ddcSMark Murray } 48281cb6ddcSMark Murray 48381cb6ddcSMark Murray void 4848fa113e5SMark Murray cfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 48581cb6ddcSMark Murray { 48681cb6ddcSMark Murray fb64_printsub(data, cnt, buf, buflen, "CFB64"); 48781cb6ddcSMark Murray } 48881cb6ddcSMark Murray 48981cb6ddcSMark Murray void 4908fa113e5SMark Murray ofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 49181cb6ddcSMark Murray { 49281cb6ddcSMark Murray fb64_printsub(data, cnt, buf, buflen, "OFB64"); 49381cb6ddcSMark Murray } 49481cb6ddcSMark Murray 49581cb6ddcSMark Murray void 4968fa113e5SMark Murray fb64_stream_iv(Block seed, struct stinfo *stp) 49781cb6ddcSMark Murray { 49881cb6ddcSMark Murray 49981cb6ddcSMark Murray memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); 50081cb6ddcSMark Murray memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); 50181cb6ddcSMark Murray 50204c426ccSMark Murray des_key_sched((Block *)stp->str_ikey, stp->str_sched); 50381cb6ddcSMark Murray 50481cb6ddcSMark Murray stp->str_index = sizeof(Block); 50581cb6ddcSMark Murray } 50681cb6ddcSMark Murray 50781cb6ddcSMark Murray void 5088fa113e5SMark Murray fb64_stream_key(Block key, struct stinfo *stp) 50981cb6ddcSMark Murray { 51081cb6ddcSMark Murray memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); 51104c426ccSMark Murray des_key_sched((Block *)key, stp->str_sched); 51281cb6ddcSMark Murray 51381cb6ddcSMark Murray memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); 51481cb6ddcSMark Murray 51581cb6ddcSMark Murray stp->str_index = sizeof(Block); 51681cb6ddcSMark Murray } 51781cb6ddcSMark Murray 51881cb6ddcSMark Murray /* 51981cb6ddcSMark Murray * DES 64 bit Cipher Feedback 52081cb6ddcSMark Murray * 52181cb6ddcSMark Murray * key --->+-----+ 52281cb6ddcSMark Murray * +->| DES |--+ 52381cb6ddcSMark Murray * | +-----+ | 52481cb6ddcSMark Murray * | v 52581cb6ddcSMark Murray * INPUT --(--------->(+)+---> DATA 52681cb6ddcSMark Murray * | | 52781cb6ddcSMark Murray * +-------------+ 52881cb6ddcSMark Murray * 52981cb6ddcSMark Murray * 53081cb6ddcSMark Murray * Given: 53181cb6ddcSMark Murray * iV: Initial vector, 64 bits (8 bytes) long. 53281cb6ddcSMark Murray * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 53381cb6ddcSMark Murray * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 53481cb6ddcSMark Murray * 53581cb6ddcSMark Murray * V0 = DES(iV, key) 53681cb6ddcSMark Murray * On = Dn ^ Vn 53781cb6ddcSMark Murray * V(n+1) = DES(On, key) 53881cb6ddcSMark Murray */ 53981cb6ddcSMark Murray 54081cb6ddcSMark Murray void 5418fa113e5SMark Murray cfb64_encrypt(unsigned char *s, int c) 54281cb6ddcSMark Murray { 5438fa113e5SMark Murray struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; 5448fa113e5SMark Murray int idx; 54581cb6ddcSMark Murray 5468fa113e5SMark Murray idx = stp->str_index; 54781cb6ddcSMark Murray while (c-- > 0) { 5488fa113e5SMark Murray if (idx == sizeof(Block)) { 54981cb6ddcSMark Murray Block b; 55004c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 55181cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 5528fa113e5SMark Murray idx = 0; 55381cb6ddcSMark Murray } 55481cb6ddcSMark Murray 55581cb6ddcSMark Murray /* On encryption, we store (feed ^ data) which is cypher */ 5568fa113e5SMark Murray *s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s); 55781cb6ddcSMark Murray s++; 5588fa113e5SMark Murray idx++; 55981cb6ddcSMark Murray } 5608fa113e5SMark Murray stp->str_index = idx; 56181cb6ddcSMark Murray } 56281cb6ddcSMark Murray 56381cb6ddcSMark Murray int 5648fa113e5SMark Murray cfb64_decrypt(int data) 56581cb6ddcSMark Murray { 5668fa113e5SMark Murray struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 5678fa113e5SMark Murray int idx; 56881cb6ddcSMark Murray 56981cb6ddcSMark Murray if (data == -1) { 57081cb6ddcSMark Murray /* 57181cb6ddcSMark Murray * Back up one byte. It is assumed that we will 57281cb6ddcSMark Murray * never back up more than one byte. If we do, this 57381cb6ddcSMark Murray * may or may not work. 57481cb6ddcSMark Murray */ 57581cb6ddcSMark Murray if (stp->str_index) 57681cb6ddcSMark Murray --stp->str_index; 57781cb6ddcSMark Murray return(0); 57881cb6ddcSMark Murray } 57981cb6ddcSMark Murray 5808fa113e5SMark Murray idx = stp->str_index++; 5818fa113e5SMark Murray if (idx == sizeof(Block)) { 58281cb6ddcSMark Murray Block b; 58304c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 58481cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 58581cb6ddcSMark Murray stp->str_index = 1; /* Next time will be 1 */ 5868fa113e5SMark Murray idx = 0; /* But now use 0 */ 58781cb6ddcSMark Murray } 58881cb6ddcSMark Murray 58981cb6ddcSMark Murray /* On decryption we store (data) which is cypher. */ 5908fa113e5SMark Murray stp->str_output[idx] = data; 5918fa113e5SMark Murray return(data ^ stp->str_feed[idx]); 59281cb6ddcSMark Murray } 59381cb6ddcSMark Murray 59481cb6ddcSMark Murray /* 59581cb6ddcSMark Murray * DES 64 bit Output Feedback 59681cb6ddcSMark Murray * 59781cb6ddcSMark Murray * key --->+-----+ 59881cb6ddcSMark Murray * +->| DES |--+ 59981cb6ddcSMark Murray * | +-----+ | 60081cb6ddcSMark Murray * +-----------+ 60181cb6ddcSMark Murray * v 60281cb6ddcSMark Murray * INPUT -------->(+) ----> DATA 60381cb6ddcSMark Murray * 60481cb6ddcSMark Murray * Given: 60581cb6ddcSMark Murray * iV: Initial vector, 64 bits (8 bytes) long. 60681cb6ddcSMark Murray * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 60781cb6ddcSMark Murray * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 60881cb6ddcSMark Murray * 60981cb6ddcSMark Murray * V0 = DES(iV, key) 61081cb6ddcSMark Murray * V(n+1) = DES(Vn, key) 61181cb6ddcSMark Murray * On = Dn ^ Vn 61281cb6ddcSMark Murray */ 61381cb6ddcSMark Murray void 6148fa113e5SMark Murray ofb64_encrypt(unsigned char *s, int c) 61581cb6ddcSMark Murray { 6168fa113e5SMark Murray struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; 6178fa113e5SMark Murray int idx; 61881cb6ddcSMark Murray 6198fa113e5SMark Murray idx = stp->str_index; 62081cb6ddcSMark Murray while (c-- > 0) { 6218fa113e5SMark Murray if (idx == sizeof(Block)) { 62281cb6ddcSMark Murray Block b; 62304c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 62481cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 6258fa113e5SMark Murray idx = 0; 62681cb6ddcSMark Murray } 6278fa113e5SMark Murray *s++ ^= stp->str_feed[idx]; 6288fa113e5SMark Murray idx++; 62981cb6ddcSMark Murray } 6308fa113e5SMark Murray stp->str_index = idx; 63181cb6ddcSMark Murray } 63281cb6ddcSMark Murray 63381cb6ddcSMark Murray int 6348fa113e5SMark Murray ofb64_decrypt(int data) 63581cb6ddcSMark Murray { 6368fa113e5SMark Murray struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 6378fa113e5SMark Murray int idx; 63881cb6ddcSMark Murray 63981cb6ddcSMark Murray if (data == -1) { 64081cb6ddcSMark Murray /* 64181cb6ddcSMark Murray * Back up one byte. It is assumed that we will 64281cb6ddcSMark Murray * never back up more than one byte. If we do, this 64381cb6ddcSMark Murray * may or may not work. 64481cb6ddcSMark Murray */ 64581cb6ddcSMark Murray if (stp->str_index) 64681cb6ddcSMark Murray --stp->str_index; 64781cb6ddcSMark Murray return(0); 64881cb6ddcSMark Murray } 64981cb6ddcSMark Murray 6508fa113e5SMark Murray idx = stp->str_index++; 6518fa113e5SMark Murray if (idx == sizeof(Block)) { 65281cb6ddcSMark Murray Block b; 65304c426ccSMark Murray des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 65481cb6ddcSMark Murray memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 65581cb6ddcSMark Murray stp->str_index = 1; /* Next time will be 1 */ 6568fa113e5SMark Murray idx = 0; /* But now use 0 */ 65781cb6ddcSMark Murray } 65881cb6ddcSMark Murray 6598fa113e5SMark Murray return(data ^ stp->str_feed[idx]); 66081cb6ddcSMark Murray } 66181cb6ddcSMark Murray # endif /* AUTHENTICATION */ 66281cb6ddcSMark Murray #endif /* ENCRYPTION */ 663