129088Smarkm/*- 229088Smarkm * Copyright (c) 1991, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 34114630Sobrien#if 0 3529088Smarkm#ifndef lint 3629181Smarkmstatic const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; 3729088Smarkm#endif /* not lint */ 38114630Sobrien#endif 39114630Sobrien#include <sys/cdefs.h> 40114630Sobrien__FBSDID("$FreeBSD$"); 4129088Smarkm 4229088Smarkm#ifdef ENCRYPTION 4329088Smarkm# ifdef AUTHENTICATION 4429088Smarkm#include <arpa/telnet.h> 4587139Smarkm#include <openssl/des.h> 4629088Smarkm#include <stdio.h> 4729088Smarkm#include <stdlib.h> 4887139Smarkm#include <string.h> 4929088Smarkm 5029088Smarkm#include "encrypt.h" 5129088Smarkm#include "key-proto.h" 5229088Smarkm#include "misc-proto.h" 5329088Smarkm 5481965Smarkmextern int encrypt_debug_mode; 5529088Smarkm 5629088Smarkm#define CFB 0 5729088Smarkm#define OFB 1 5829088Smarkm 5929088Smarkm#define NO_SEND_IV 1 6029088Smarkm#define NO_RECV_IV 2 6129088Smarkm#define NO_KEYID 4 6229088Smarkm#define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) 6329088Smarkm#define SUCCESS 0 6429088Smarkm#define FAILED -1 6529088Smarkm 6629088Smarkm 6729088Smarkmstruct fb { 6829088Smarkm Block krbdes_key; 6929088Smarkm Schedule krbdes_sched; 7029088Smarkm Block temp_feed; 7129088Smarkm unsigned char fb_feed[64]; 7229088Smarkm int need_start; 7329088Smarkm int state[2]; 7429088Smarkm int keyid[2]; 7529088Smarkm struct stinfo { 7629088Smarkm Block str_output; 7729088Smarkm Block str_feed; 7829088Smarkm Block str_iv; 7929088Smarkm Block str_ikey; 8029088Smarkm Schedule str_sched; 8129088Smarkm int str_index; 8229088Smarkm int str_flagshift; 8329088Smarkm } streams[2]; 8429088Smarkm}; 8529088Smarkm 8629088Smarkmstatic struct fb fb[2]; 8729088Smarkm 8829088Smarkmstruct keyidlist { 8987139Smarkm const char *keyid; 9029088Smarkm int keyidlen; 9129088Smarkm char *key; 9229088Smarkm int keylen; 9329088Smarkm int flags; 9429088Smarkm} keyidlist [] = { 9529088Smarkm { "\0", 1, 0, 0, 0 }, /* default key of zero */ 9629088Smarkm { 0, 0, 0, 0, 0 } 9729088Smarkm}; 9829088Smarkm 9929088Smarkm#define KEYFLAG_MASK 03 10029088Smarkm 10129088Smarkm#define KEYFLAG_NOINIT 00 10229088Smarkm#define KEYFLAG_INIT 01 10329088Smarkm#define KEYFLAG_OK 02 10429088Smarkm#define KEYFLAG_BAD 03 10529088Smarkm 10629088Smarkm#define KEYFLAG_SHIFT 2 10729088Smarkm 10829088Smarkm#define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) 10929088Smarkm 11029088Smarkm#define FB64_IV 1 11129088Smarkm#define FB64_IV_OK 2 11229088Smarkm#define FB64_IV_BAD 3 11329088Smarkm 11429088Smarkm 11587155Smarkmvoid fb64_stream_iv(Block, struct stinfo *); 11687155Smarkmvoid fb64_init(struct fb *); 11787155Smarkmstatic int fb64_start(struct fb *, int, int); 11887155Smarkmint fb64_is(unsigned char *, int, struct fb *); 11987155Smarkmint fb64_reply(unsigned char *, int, struct fb *); 12087155Smarkmstatic void fb64_session(Session_Key *, int, struct fb *); 12187155Smarkmvoid fb64_stream_key(Block, struct stinfo *); 12287155Smarkmint fb64_keyid(int, unsigned char *, int *, struct fb *); 12329088Smarkm 12487139Smarkmvoid 12587139Smarkmcfb64_init(int server __unused) 12629088Smarkm{ 12729088Smarkm fb64_init(&fb[CFB]); 12829088Smarkm fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; 12929088Smarkm fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); 13029088Smarkm fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); 13129088Smarkm} 13229088Smarkm 13387139Smarkmvoid 13487139Smarkmofb64_init(int server __unused) 13529088Smarkm{ 13629088Smarkm fb64_init(&fb[OFB]); 13729088Smarkm fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; 13829088Smarkm fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); 13929088Smarkm fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); 14029088Smarkm} 14129088Smarkm 14287139Smarkmvoid 14387139Smarkmfb64_init(struct fb *fbp) 14429088Smarkm{ 14529088Smarkm memset((void *)fbp, 0, sizeof(*fbp)); 14629088Smarkm fbp->state[0] = fbp->state[1] = FAILED; 14729088Smarkm fbp->fb_feed[0] = IAC; 14829088Smarkm fbp->fb_feed[1] = SB; 14929088Smarkm fbp->fb_feed[2] = TELOPT_ENCRYPT; 15029088Smarkm fbp->fb_feed[3] = ENCRYPT_IS; 15129088Smarkm} 15229088Smarkm 15329088Smarkm/* 15429088Smarkm * Returns: 15529088Smarkm * -1: some error. Negotiation is done, encryption not ready. 15629088Smarkm * 0: Successful, initial negotiation all done. 15729088Smarkm * 1: successful, negotiation not done yet. 15829088Smarkm * 2: Not yet. Other things (like getting the key from 15929088Smarkm * Kerberos) have to happen before we can continue. 16029088Smarkm */ 16187139Smarkmint 16287139Smarkmcfb64_start(int dir, int server) 16329088Smarkm{ 16429088Smarkm return(fb64_start(&fb[CFB], dir, server)); 16529088Smarkm} 16687139Smarkm 16787139Smarkmint 16887139Smarkmofb64_start(int dir, int server) 16929088Smarkm{ 17029088Smarkm return(fb64_start(&fb[OFB], dir, server)); 17129088Smarkm} 17229088Smarkm 17387139Smarkmstatic int 17487139Smarkmfb64_start(struct fb *fbp, int dir, int server __unused) 17529088Smarkm{ 17687139Smarkm size_t x; 17729088Smarkm unsigned char *p; 17887139Smarkm int state; 17929088Smarkm 18029088Smarkm switch (dir) { 18129088Smarkm case DIR_DECRYPT: 18229088Smarkm /* 18329088Smarkm * This is simply a request to have the other side 18429088Smarkm * start output (our input). He will negotiate an 18529088Smarkm * IV so we need not look for it. 18629088Smarkm */ 18729088Smarkm state = fbp->state[dir-1]; 18829088Smarkm if (state == FAILED) 18929088Smarkm state = IN_PROGRESS; 19029088Smarkm break; 19129088Smarkm 19229088Smarkm case DIR_ENCRYPT: 19329088Smarkm state = fbp->state[dir-1]; 19429088Smarkm if (state == FAILED) 19529088Smarkm state = IN_PROGRESS; 19629088Smarkm else if ((state & NO_SEND_IV) == 0) 19729088Smarkm break; 19829088Smarkm 19929088Smarkm if (!VALIDKEY(fbp->krbdes_key)) { 20029088Smarkm fbp->need_start = 1; 20129088Smarkm break; 20229088Smarkm } 20329088Smarkm state &= ~NO_SEND_IV; 20429088Smarkm state |= NO_RECV_IV; 20529088Smarkm if (encrypt_debug_mode) 20629088Smarkm printf("Creating new feed\r\n"); 20729088Smarkm /* 20829088Smarkm * Create a random feed and send it over. 20929088Smarkm */ 210110049Snectar des_random_key((Block *)fbp->temp_feed); 21129181Smarkm des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, 21229088Smarkm fbp->krbdes_sched, 1); 21329088Smarkm p = fbp->fb_feed + 3; 21429088Smarkm *p++ = ENCRYPT_IS; 21529088Smarkm p++; 21629088Smarkm *p++ = FB64_IV; 21729088Smarkm for (x = 0; x < sizeof(Block); ++x) { 21829088Smarkm if ((*p++ = fbp->temp_feed[x]) == IAC) 21929088Smarkm *p++ = IAC; 22029088Smarkm } 22129088Smarkm *p++ = IAC; 22229088Smarkm *p++ = SE; 22329088Smarkm printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 22429088Smarkm net_write(fbp->fb_feed, p - fbp->fb_feed); 22529088Smarkm break; 22629088Smarkm default: 22729088Smarkm return(FAILED); 22829088Smarkm } 22929088Smarkm return(fbp->state[dir-1] = state); 23029088Smarkm} 23129088Smarkm 23229088Smarkm/* 23329088Smarkm * Returns: 23429088Smarkm * -1: some error. Negotiation is done, encryption not ready. 23529088Smarkm * 0: Successful, initial negotiation all done. 23629088Smarkm * 1: successful, negotiation not done yet. 23729088Smarkm */ 23887139Smarkmint 23987139Smarkmcfb64_is(unsigned char *data, int cnt) 24029088Smarkm{ 24129088Smarkm return(fb64_is(data, cnt, &fb[CFB])); 24229088Smarkm} 24387139Smarkm 24487139Smarkmint 24587139Smarkmofb64_is(unsigned char *data, int cnt) 24629088Smarkm{ 24729088Smarkm return(fb64_is(data, cnt, &fb[OFB])); 24829088Smarkm} 24929088Smarkm 25087139Smarkmint 25187139Smarkmfb64_is(unsigned char *data, int cnt, struct fb *fbp) 25229088Smarkm{ 25329088Smarkm unsigned char *p; 25487139Smarkm int state = fbp->state[DIR_DECRYPT-1]; 25529088Smarkm 25629088Smarkm if (cnt-- < 1) 25729088Smarkm goto failure; 25829088Smarkm 25929088Smarkm switch (*data++) { 26029088Smarkm case FB64_IV: 26129088Smarkm if (cnt != sizeof(Block)) { 26229088Smarkm if (encrypt_debug_mode) 26329088Smarkm printf("CFB64: initial vector failed on size\r\n"); 26429088Smarkm state = FAILED; 26529088Smarkm goto failure; 26629088Smarkm } 26729088Smarkm 26829088Smarkm if (encrypt_debug_mode) 26929088Smarkm printf("CFB64: initial vector received\r\n"); 27029088Smarkm 27129088Smarkm if (encrypt_debug_mode) 27229088Smarkm printf("Initializing Decrypt stream\r\n"); 27329088Smarkm 27429088Smarkm fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); 27529088Smarkm 27629088Smarkm p = fbp->fb_feed + 3; 27729088Smarkm *p++ = ENCRYPT_REPLY; 27829088Smarkm p++; 27929088Smarkm *p++ = FB64_IV_OK; 28029088Smarkm *p++ = IAC; 28129088Smarkm *p++ = SE; 28229088Smarkm printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 28329088Smarkm net_write(fbp->fb_feed, p - fbp->fb_feed); 28429088Smarkm 28529088Smarkm state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; 28629088Smarkm break; 28729088Smarkm 28829088Smarkm default: 28929088Smarkm if (encrypt_debug_mode) { 29029088Smarkm printf("Unknown option type: %d\r\n", *(data-1)); 29129088Smarkm printd(data, cnt); 29229088Smarkm printf("\r\n"); 29329088Smarkm } 29429088Smarkm /* FALL THROUGH */ 29529088Smarkm failure: 29629088Smarkm /* 29729088Smarkm * We failed. Send an FB64_IV_BAD option 29829088Smarkm * to the other side so it will know that 29929088Smarkm * things failed. 30029088Smarkm */ 30129088Smarkm p = fbp->fb_feed + 3; 30229088Smarkm *p++ = ENCRYPT_REPLY; 30329088Smarkm p++; 30429088Smarkm *p++ = FB64_IV_BAD; 30529088Smarkm *p++ = IAC; 30629088Smarkm *p++ = SE; 30729088Smarkm printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 30829088Smarkm net_write(fbp->fb_feed, p - fbp->fb_feed); 30929088Smarkm 31029088Smarkm break; 31129088Smarkm } 31229088Smarkm return(fbp->state[DIR_DECRYPT-1] = state); 31329088Smarkm} 31429088Smarkm 31529088Smarkm/* 31629088Smarkm * Returns: 31729088Smarkm * -1: some error. Negotiation is done, encryption not ready. 31829088Smarkm * 0: Successful, initial negotiation all done. 31929088Smarkm * 1: successful, negotiation not done yet. 32029088Smarkm */ 32187139Smarkmint 32287139Smarkmcfb64_reply(unsigned char *data, int cnt) 32329088Smarkm{ 32429088Smarkm return(fb64_reply(data, cnt, &fb[CFB])); 32529088Smarkm} 32687139Smarkm 32787139Smarkmint 32887139Smarkmofb64_reply(unsigned char *data, int cnt) 32929088Smarkm{ 33029088Smarkm return(fb64_reply(data, cnt, &fb[OFB])); 33129088Smarkm} 33229088Smarkm 33387139Smarkmint 33487139Smarkmfb64_reply(unsigned char *data, int cnt, struct fb *fbp) 33529088Smarkm{ 33687139Smarkm int state = fbp->state[DIR_ENCRYPT-1]; 33729088Smarkm 33829088Smarkm if (cnt-- < 1) 33929088Smarkm goto failure; 34029088Smarkm 34129088Smarkm switch (*data++) { 34229088Smarkm case FB64_IV_OK: 34329088Smarkm fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 34429088Smarkm if (state == FAILED) 34529088Smarkm state = IN_PROGRESS; 34629088Smarkm state &= ~NO_RECV_IV; 34787139Smarkm encrypt_send_keyid(DIR_ENCRYPT, "\0", 1, 1); 34829088Smarkm break; 34929088Smarkm 35029088Smarkm case FB64_IV_BAD: 35129088Smarkm memset(fbp->temp_feed, 0, sizeof(Block)); 35229088Smarkm fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 35329088Smarkm state = FAILED; 35429088Smarkm break; 35529088Smarkm 35629088Smarkm default: 35729088Smarkm if (encrypt_debug_mode) { 35829088Smarkm printf("Unknown option type: %d\r\n", data[-1]); 35929088Smarkm printd(data, cnt); 36029088Smarkm printf("\r\n"); 36129088Smarkm } 36229088Smarkm /* FALL THROUGH */ 36329088Smarkm failure: 36429088Smarkm state = FAILED; 36529088Smarkm break; 36629088Smarkm } 36729088Smarkm return(fbp->state[DIR_ENCRYPT-1] = state); 36829088Smarkm} 36929088Smarkm 37087139Smarkmvoid 37187139Smarkmcfb64_session(Session_Key *key, int server) 37229088Smarkm{ 37329088Smarkm fb64_session(key, server, &fb[CFB]); 37429088Smarkm} 37529088Smarkm 37687139Smarkmvoid 37787139Smarkmofb64_session(Session_Key *key, int server) 37829088Smarkm{ 37929088Smarkm fb64_session(key, server, &fb[OFB]); 38029088Smarkm} 38129088Smarkm 38287139Smarkmstatic void 38387139Smarkmfb64_session(Session_Key *key, int server, struct fb *fbp) 38429088Smarkm{ 38529088Smarkm if (!key || key->type != SK_DES) { 38629088Smarkm if (encrypt_debug_mode) 38729088Smarkm printf("Can't set krbdes's session key (%d != %d)\r\n", 38829088Smarkm key ? key->type : -1, SK_DES); 38929088Smarkm return; 39029088Smarkm } 39129088Smarkm memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); 39229088Smarkm 39329088Smarkm fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); 39429088Smarkm fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); 39529088Smarkm 39629181Smarkm des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); 39729088Smarkm /* 39829088Smarkm * Now look to see if krbdes_start() was was waiting for 39929088Smarkm * the key to show up. If so, go ahead an call it now 40029088Smarkm * that we have the key. 40129088Smarkm */ 40229088Smarkm if (fbp->need_start) { 40329088Smarkm fbp->need_start = 0; 40429088Smarkm fb64_start(fbp, DIR_ENCRYPT, server); 40529088Smarkm } 40629088Smarkm} 40729088Smarkm 40829088Smarkm/* 40929088Smarkm * We only accept a keyid of 0. If we get a keyid of 41029088Smarkm * 0, then mark the state as SUCCESS. 41129088Smarkm */ 41287139Smarkmint 41387139Smarkmcfb64_keyid(int dir, unsigned char *kp, int *lenp) 41429088Smarkm{ 41529088Smarkm return(fb64_keyid(dir, kp, lenp, &fb[CFB])); 41629088Smarkm} 41729088Smarkm 41887139Smarkmint 41987139Smarkmofb64_keyid(int dir, unsigned char *kp, int *lenp) 42029088Smarkm{ 42129088Smarkm return(fb64_keyid(dir, kp, lenp, &fb[OFB])); 42229088Smarkm} 42329088Smarkm 42487139Smarkmint 42587139Smarkmfb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp) 42629088Smarkm{ 42787139Smarkm int state = fbp->state[dir-1]; 42829088Smarkm 42929088Smarkm if (*lenp != 1 || (*kp != '\0')) { 43029088Smarkm *lenp = 0; 43129088Smarkm return(state); 43229088Smarkm } 43329088Smarkm 43429088Smarkm if (state == FAILED) 43529088Smarkm state = IN_PROGRESS; 43629088Smarkm 43729088Smarkm state &= ~NO_KEYID; 43829088Smarkm 43929088Smarkm return(fbp->state[dir-1] = state); 44029088Smarkm} 44129088Smarkm 44287139Smarkmvoid 44387139Smarkmfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen, const char *type) 44429088Smarkm{ 44529088Smarkm char lbuf[32]; 44687139Smarkm int i; 44729088Smarkm char *cp; 44829088Smarkm 44929088Smarkm buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 45029088Smarkm buflen -= 1; 45129088Smarkm 45229088Smarkm switch(data[2]) { 45329088Smarkm case FB64_IV: 45429088Smarkm sprintf(lbuf, "%s_IV", type); 45529088Smarkm cp = lbuf; 45629088Smarkm goto common; 45729088Smarkm 45829088Smarkm case FB64_IV_OK: 45929088Smarkm sprintf(lbuf, "%s_IV_OK", type); 46029088Smarkm cp = lbuf; 46129088Smarkm goto common; 46229088Smarkm 46329088Smarkm case FB64_IV_BAD: 46429088Smarkm sprintf(lbuf, "%s_IV_BAD", type); 46529088Smarkm cp = lbuf; 46629088Smarkm goto common; 46729088Smarkm 46829088Smarkm default: 46929088Smarkm sprintf(lbuf, " %d (unknown)", data[2]); 47029088Smarkm cp = lbuf; 47129088Smarkm common: 47229088Smarkm for (; (buflen > 0) && (*buf = *cp++); buf++) 47329088Smarkm buflen--; 47429088Smarkm for (i = 3; i < cnt; i++) { 47529088Smarkm sprintf(lbuf, " %d", data[i]); 47629088Smarkm for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) 47729088Smarkm buflen--; 47829088Smarkm } 47929088Smarkm break; 48029088Smarkm } 48129088Smarkm} 48229088Smarkm 48387139Smarkmvoid 48487139Smarkmcfb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 48529088Smarkm{ 48629088Smarkm fb64_printsub(data, cnt, buf, buflen, "CFB64"); 48729088Smarkm} 48829088Smarkm 48987139Smarkmvoid 49087139Smarkmofb64_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 49129088Smarkm{ 49229088Smarkm fb64_printsub(data, cnt, buf, buflen, "OFB64"); 49329088Smarkm} 49429088Smarkm 49587139Smarkmvoid 49687139Smarkmfb64_stream_iv(Block seed, struct stinfo *stp) 49729088Smarkm{ 49829088Smarkm 49929088Smarkm memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); 50029088Smarkm memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); 50129088Smarkm 50229181Smarkm des_key_sched((Block *)stp->str_ikey, stp->str_sched); 50329088Smarkm 50429088Smarkm stp->str_index = sizeof(Block); 50529088Smarkm} 50629088Smarkm 50787139Smarkmvoid 50887139Smarkmfb64_stream_key(Block key, struct stinfo *stp) 50929088Smarkm{ 51029088Smarkm memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); 51129181Smarkm des_key_sched((Block *)key, stp->str_sched); 51229088Smarkm 51329088Smarkm memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); 51429088Smarkm 51529088Smarkm stp->str_index = sizeof(Block); 51629088Smarkm} 51729088Smarkm 51829088Smarkm/* 51929088Smarkm * DES 64 bit Cipher Feedback 52029088Smarkm * 52129088Smarkm * key --->+-----+ 52229088Smarkm * +->| DES |--+ 52329088Smarkm * | +-----+ | 52429088Smarkm * | v 52529088Smarkm * INPUT --(--------->(+)+---> DATA 52629088Smarkm * | | 52729088Smarkm * +-------------+ 52829088Smarkm * 52929088Smarkm * 53029088Smarkm * Given: 53129088Smarkm * iV: Initial vector, 64 bits (8 bytes) long. 53229088Smarkm * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 53329088Smarkm * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 53429088Smarkm * 53529088Smarkm * V0 = DES(iV, key) 53629088Smarkm * On = Dn ^ Vn 53729088Smarkm * V(n+1) = DES(On, key) 53829088Smarkm */ 53929088Smarkm 54087139Smarkmvoid 54187139Smarkmcfb64_encrypt(unsigned char *s, int c) 54229088Smarkm{ 54387139Smarkm struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; 54487139Smarkm int idx; 54529088Smarkm 54687139Smarkm idx = stp->str_index; 54729088Smarkm while (c-- > 0) { 54887139Smarkm if (idx == sizeof(Block)) { 54929088Smarkm Block b; 55029181Smarkm des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 55129088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 55287139Smarkm idx = 0; 55329088Smarkm } 55429088Smarkm 55529088Smarkm /* On encryption, we store (feed ^ data) which is cypher */ 55687139Smarkm *s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s); 55729088Smarkm s++; 55887139Smarkm idx++; 55929088Smarkm } 56087139Smarkm stp->str_index = idx; 56129088Smarkm} 56229088Smarkm 56387139Smarkmint 56487139Smarkmcfb64_decrypt(int data) 56529088Smarkm{ 56687139Smarkm struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 56787139Smarkm int idx; 56829088Smarkm 56929088Smarkm if (data == -1) { 57029088Smarkm /* 57129088Smarkm * Back up one byte. It is assumed that we will 57229088Smarkm * never back up more than one byte. If we do, this 57329088Smarkm * may or may not work. 57429088Smarkm */ 57529088Smarkm if (stp->str_index) 57629088Smarkm --stp->str_index; 57729088Smarkm return(0); 57829088Smarkm } 57929088Smarkm 58087139Smarkm idx = stp->str_index++; 58187139Smarkm if (idx == sizeof(Block)) { 58229088Smarkm Block b; 58329181Smarkm des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 58429088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 58529088Smarkm stp->str_index = 1; /* Next time will be 1 */ 58687139Smarkm idx = 0; /* But now use 0 */ 58729088Smarkm } 58829088Smarkm 58929088Smarkm /* On decryption we store (data) which is cypher. */ 59087139Smarkm stp->str_output[idx] = data; 59187139Smarkm return(data ^ stp->str_feed[idx]); 59229088Smarkm} 59329088Smarkm 59429088Smarkm/* 59529088Smarkm * DES 64 bit Output Feedback 59629088Smarkm * 59729088Smarkm * key --->+-----+ 59829088Smarkm * +->| DES |--+ 59929088Smarkm * | +-----+ | 60029088Smarkm * +-----------+ 60129088Smarkm * v 60229088Smarkm * INPUT -------->(+) ----> DATA 60329088Smarkm * 60429088Smarkm * Given: 60529088Smarkm * iV: Initial vector, 64 bits (8 bytes) long. 60629088Smarkm * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 60729088Smarkm * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 60829088Smarkm * 60929088Smarkm * V0 = DES(iV, key) 61029088Smarkm * V(n+1) = DES(Vn, key) 61129088Smarkm * On = Dn ^ Vn 61229088Smarkm */ 61387139Smarkmvoid 61487139Smarkmofb64_encrypt(unsigned char *s, int c) 61529088Smarkm{ 61687139Smarkm struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; 61787139Smarkm int idx; 61829088Smarkm 61987139Smarkm idx = stp->str_index; 62029088Smarkm while (c-- > 0) { 62187139Smarkm if (idx == sizeof(Block)) { 62229088Smarkm Block b; 62329181Smarkm des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 62429088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 62587139Smarkm idx = 0; 62629088Smarkm } 62787139Smarkm *s++ ^= stp->str_feed[idx]; 62887139Smarkm idx++; 62929088Smarkm } 63087139Smarkm stp->str_index = idx; 63129088Smarkm} 63229088Smarkm 63387139Smarkmint 63487139Smarkmofb64_decrypt(int data) 63529088Smarkm{ 63687139Smarkm struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 63787139Smarkm int idx; 63829088Smarkm 63929088Smarkm if (data == -1) { 64029088Smarkm /* 64129088Smarkm * Back up one byte. It is assumed that we will 64229088Smarkm * never back up more than one byte. If we do, this 64329088Smarkm * may or may not work. 64429088Smarkm */ 64529088Smarkm if (stp->str_index) 64629088Smarkm --stp->str_index; 64729088Smarkm return(0); 64829088Smarkm } 64929088Smarkm 65087139Smarkm idx = stp->str_index++; 65187139Smarkm if (idx == sizeof(Block)) { 65229088Smarkm Block b; 65329181Smarkm des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 65429088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 65529088Smarkm stp->str_index = 1; /* Next time will be 1 */ 65687139Smarkm idx = 0; /* But now use 0 */ 65729088Smarkm } 65829088Smarkm 65987139Smarkm return(data ^ stp->str_feed[idx]); 66029088Smarkm} 66129088Smarkm# endif /* AUTHENTICATION */ 66229088Smarkm#endif /* ENCRYPTION */ 663