enc_des.c revision 29181
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 3429088Smarkm#ifndef lint 3529181Smarkmstatic const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; 3629088Smarkm#endif /* not lint */ 3729088Smarkm 3829088Smarkm#ifdef ENCRYPTION 3929088Smarkm# ifdef AUTHENTICATION 4029088Smarkm# ifdef DES_ENCRYPTION 4129088Smarkm#include <arpa/telnet.h> 4229088Smarkm#include <stdio.h> 4329088Smarkm#ifdef __STDC__ 4429088Smarkm#include <stdlib.h> 4529088Smarkm#endif 4629088Smarkm 4729181Smarkm#include <des.h> 4829181Smarkm#include <string.h> 4929088Smarkm#include "encrypt.h" 5029088Smarkm#include "key-proto.h" 5129088Smarkm#include "misc-proto.h" 5229088Smarkm 5329088Smarkmextern encrypt_debug_mode; 5429088Smarkm 5529088Smarkm#define CFB 0 5629088Smarkm#define OFB 1 5729088Smarkm 5829088Smarkm#define NO_SEND_IV 1 5929088Smarkm#define NO_RECV_IV 2 6029088Smarkm#define NO_KEYID 4 6129088Smarkm#define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) 6229088Smarkm#define SUCCESS 0 6329088Smarkm#define FAILED -1 6429088Smarkm 6529088Smarkm 6629088Smarkmstruct fb { 6729088Smarkm Block krbdes_key; 6829088Smarkm Schedule krbdes_sched; 6929088Smarkm Block temp_feed; 7029088Smarkm unsigned char fb_feed[64]; 7129088Smarkm int need_start; 7229088Smarkm int state[2]; 7329088Smarkm int keyid[2]; 7429088Smarkm int once; 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 { 8929088Smarkm 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 11529088Smarkmvoid fb64_stream_iv P((Block, struct stinfo *)); 11629088Smarkmvoid fb64_init P((struct fb *)); 11729088Smarkmstatic int fb64_start P((struct fb *, int, int)); 11829088Smarkmint fb64_is P((unsigned char *, int, struct fb *)); 11929088Smarkmint fb64_reply P((unsigned char *, int, struct fb *)); 12029088Smarkmstatic void fb64_session P((Session_Key *, int, struct fb *)); 12129088Smarkmvoid fb64_stream_key P((Block, struct stinfo *)); 12229088Smarkmint fb64_keyid P((int, unsigned char *, int *, struct fb *)); 12329088Smarkm 12429088Smarkm void 12529088Smarkmcfb64_init(server) 12629088Smarkm int server; 12729088Smarkm{ 12829088Smarkm fb64_init(&fb[CFB]); 12929088Smarkm fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; 13029088Smarkm fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); 13129088Smarkm fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); 13229088Smarkm} 13329088Smarkm 13429088Smarkm void 13529088Smarkmofb64_init(server) 13629088Smarkm int server; 13729088Smarkm{ 13829088Smarkm fb64_init(&fb[OFB]); 13929088Smarkm fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; 14029088Smarkm fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); 14129088Smarkm fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); 14229088Smarkm} 14329088Smarkm 14429088Smarkm void 14529088Smarkmfb64_init(fbp) 14629088Smarkm register struct fb *fbp; 14729088Smarkm{ 14829088Smarkm memset((void *)fbp, 0, sizeof(*fbp)); 14929088Smarkm fbp->state[0] = fbp->state[1] = FAILED; 15029088Smarkm fbp->fb_feed[0] = IAC; 15129088Smarkm fbp->fb_feed[1] = SB; 15229088Smarkm fbp->fb_feed[2] = TELOPT_ENCRYPT; 15329088Smarkm fbp->fb_feed[3] = ENCRYPT_IS; 15429088Smarkm} 15529088Smarkm 15629088Smarkm/* 15729088Smarkm * Returns: 15829088Smarkm * -1: some error. Negotiation is done, encryption not ready. 15929088Smarkm * 0: Successful, initial negotiation all done. 16029088Smarkm * 1: successful, negotiation not done yet. 16129088Smarkm * 2: Not yet. Other things (like getting the key from 16229088Smarkm * Kerberos) have to happen before we can continue. 16329088Smarkm */ 16429088Smarkm int 16529088Smarkmcfb64_start(dir, server) 16629088Smarkm int dir; 16729088Smarkm int server; 16829088Smarkm{ 16929088Smarkm return(fb64_start(&fb[CFB], dir, server)); 17029088Smarkm} 17129088Smarkm int 17229088Smarkmofb64_start(dir, server) 17329088Smarkm int dir; 17429088Smarkm int server; 17529088Smarkm{ 17629088Smarkm return(fb64_start(&fb[OFB], dir, server)); 17729088Smarkm} 17829088Smarkm 17929088Smarkm static int 18029088Smarkmfb64_start(fbp, dir, server) 18129088Smarkm struct fb *fbp; 18229088Smarkm int dir; 18329088Smarkm int server; 18429088Smarkm{ 18529088Smarkm int x; 18629088Smarkm unsigned char *p; 18729088Smarkm register int state; 18829088Smarkm 18929088Smarkm switch (dir) { 19029088Smarkm case DIR_DECRYPT: 19129088Smarkm /* 19229088Smarkm * This is simply a request to have the other side 19329088Smarkm * start output (our input). He will negotiate an 19429088Smarkm * IV so we need not look for it. 19529088Smarkm */ 19629088Smarkm state = fbp->state[dir-1]; 19729088Smarkm if (state == FAILED) 19829088Smarkm state = IN_PROGRESS; 19929088Smarkm break; 20029088Smarkm 20129088Smarkm case DIR_ENCRYPT: 20229088Smarkm state = fbp->state[dir-1]; 20329088Smarkm if (state == FAILED) 20429088Smarkm state = IN_PROGRESS; 20529088Smarkm else if ((state & NO_SEND_IV) == 0) 20629088Smarkm break; 20729088Smarkm 20829088Smarkm if (!VALIDKEY(fbp->krbdes_key)) { 20929088Smarkm fbp->need_start = 1; 21029088Smarkm break; 21129088Smarkm } 21229088Smarkm state &= ~NO_SEND_IV; 21329088Smarkm state |= NO_RECV_IV; 21429088Smarkm if (encrypt_debug_mode) 21529088Smarkm printf("Creating new feed\r\n"); 21629088Smarkm /* 21729088Smarkm * Create a random feed and send it over. 21829088Smarkm */ 21929181Smarkm des_new_random_key((Block *)fbp->temp_feed); 22029181Smarkm des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed, 22129088Smarkm fbp->krbdes_sched, 1); 22229088Smarkm p = fbp->fb_feed + 3; 22329088Smarkm *p++ = ENCRYPT_IS; 22429088Smarkm p++; 22529088Smarkm *p++ = FB64_IV; 22629088Smarkm for (x = 0; x < sizeof(Block); ++x) { 22729088Smarkm if ((*p++ = fbp->temp_feed[x]) == IAC) 22829088Smarkm *p++ = IAC; 22929088Smarkm } 23029088Smarkm *p++ = IAC; 23129088Smarkm *p++ = SE; 23229088Smarkm printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 23329088Smarkm net_write(fbp->fb_feed, p - fbp->fb_feed); 23429088Smarkm break; 23529088Smarkm default: 23629088Smarkm return(FAILED); 23729088Smarkm } 23829088Smarkm return(fbp->state[dir-1] = state); 23929088Smarkm} 24029088Smarkm 24129088Smarkm/* 24229088Smarkm * Returns: 24329088Smarkm * -1: some error. Negotiation is done, encryption not ready. 24429088Smarkm * 0: Successful, initial negotiation all done. 24529088Smarkm * 1: successful, negotiation not done yet. 24629088Smarkm */ 24729088Smarkm int 24829088Smarkmcfb64_is(data, cnt) 24929088Smarkm unsigned char *data; 25029088Smarkm int cnt; 25129088Smarkm{ 25229088Smarkm return(fb64_is(data, cnt, &fb[CFB])); 25329088Smarkm} 25429088Smarkm int 25529088Smarkmofb64_is(data, cnt) 25629088Smarkm unsigned char *data; 25729088Smarkm int cnt; 25829088Smarkm{ 25929088Smarkm return(fb64_is(data, cnt, &fb[OFB])); 26029088Smarkm} 26129088Smarkm 26229088Smarkm int 26329088Smarkmfb64_is(data, cnt, fbp) 26429088Smarkm unsigned char *data; 26529088Smarkm int cnt; 26629088Smarkm struct fb *fbp; 26729088Smarkm{ 26829088Smarkm unsigned char *p; 26929088Smarkm register int state = fbp->state[DIR_DECRYPT-1]; 27029088Smarkm 27129088Smarkm if (cnt-- < 1) 27229088Smarkm goto failure; 27329088Smarkm 27429088Smarkm switch (*data++) { 27529088Smarkm case FB64_IV: 27629088Smarkm if (cnt != sizeof(Block)) { 27729088Smarkm if (encrypt_debug_mode) 27829088Smarkm printf("CFB64: initial vector failed on size\r\n"); 27929088Smarkm state = FAILED; 28029088Smarkm goto failure; 28129088Smarkm } 28229088Smarkm 28329088Smarkm if (encrypt_debug_mode) 28429088Smarkm printf("CFB64: initial vector received\r\n"); 28529088Smarkm 28629088Smarkm if (encrypt_debug_mode) 28729088Smarkm printf("Initializing Decrypt stream\r\n"); 28829088Smarkm 28929088Smarkm fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]); 29029088Smarkm 29129088Smarkm p = fbp->fb_feed + 3; 29229088Smarkm *p++ = ENCRYPT_REPLY; 29329088Smarkm p++; 29429088Smarkm *p++ = FB64_IV_OK; 29529088Smarkm *p++ = IAC; 29629088Smarkm *p++ = SE; 29729088Smarkm printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 29829088Smarkm net_write(fbp->fb_feed, p - fbp->fb_feed); 29929088Smarkm 30029088Smarkm state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; 30129088Smarkm break; 30229088Smarkm 30329088Smarkm default: 30429088Smarkm if (encrypt_debug_mode) { 30529088Smarkm printf("Unknown option type: %d\r\n", *(data-1)); 30629088Smarkm printd(data, cnt); 30729088Smarkm printf("\r\n"); 30829088Smarkm } 30929088Smarkm /* FALL THROUGH */ 31029088Smarkm failure: 31129088Smarkm /* 31229088Smarkm * We failed. Send an FB64_IV_BAD option 31329088Smarkm * to the other side so it will know that 31429088Smarkm * things failed. 31529088Smarkm */ 31629088Smarkm p = fbp->fb_feed + 3; 31729088Smarkm *p++ = ENCRYPT_REPLY; 31829088Smarkm p++; 31929088Smarkm *p++ = FB64_IV_BAD; 32029088Smarkm *p++ = IAC; 32129088Smarkm *p++ = SE; 32229088Smarkm printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); 32329088Smarkm net_write(fbp->fb_feed, p - fbp->fb_feed); 32429088Smarkm 32529088Smarkm break; 32629088Smarkm } 32729088Smarkm return(fbp->state[DIR_DECRYPT-1] = state); 32829088Smarkm} 32929088Smarkm 33029088Smarkm/* 33129088Smarkm * Returns: 33229088Smarkm * -1: some error. Negotiation is done, encryption not ready. 33329088Smarkm * 0: Successful, initial negotiation all done. 33429088Smarkm * 1: successful, negotiation not done yet. 33529088Smarkm */ 33629088Smarkm int 33729088Smarkmcfb64_reply(data, cnt) 33829088Smarkm unsigned char *data; 33929088Smarkm int cnt; 34029088Smarkm{ 34129088Smarkm return(fb64_reply(data, cnt, &fb[CFB])); 34229088Smarkm} 34329088Smarkm int 34429088Smarkmofb64_reply(data, cnt) 34529088Smarkm unsigned char *data; 34629088Smarkm int cnt; 34729088Smarkm{ 34829088Smarkm return(fb64_reply(data, cnt, &fb[OFB])); 34929088Smarkm} 35029088Smarkm 35129088Smarkm 35229088Smarkm int 35329088Smarkmfb64_reply(data, cnt, fbp) 35429088Smarkm unsigned char *data; 35529088Smarkm int cnt; 35629088Smarkm struct fb *fbp; 35729088Smarkm{ 35829088Smarkm register int state = fbp->state[DIR_ENCRYPT-1]; 35929088Smarkm 36029088Smarkm if (cnt-- < 1) 36129088Smarkm goto failure; 36229088Smarkm 36329088Smarkm switch (*data++) { 36429088Smarkm case FB64_IV_OK: 36529088Smarkm fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 36629088Smarkm if (state == FAILED) 36729088Smarkm state = IN_PROGRESS; 36829088Smarkm state &= ~NO_RECV_IV; 36929088Smarkm encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); 37029088Smarkm break; 37129088Smarkm 37229088Smarkm case FB64_IV_BAD: 37329088Smarkm memset(fbp->temp_feed, 0, sizeof(Block)); 37429088Smarkm fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); 37529088Smarkm state = FAILED; 37629088Smarkm break; 37729088Smarkm 37829088Smarkm default: 37929088Smarkm if (encrypt_debug_mode) { 38029088Smarkm printf("Unknown option type: %d\r\n", data[-1]); 38129088Smarkm printd(data, cnt); 38229088Smarkm printf("\r\n"); 38329088Smarkm } 38429088Smarkm /* FALL THROUGH */ 38529088Smarkm failure: 38629088Smarkm state = FAILED; 38729088Smarkm break; 38829088Smarkm } 38929088Smarkm return(fbp->state[DIR_ENCRYPT-1] = state); 39029088Smarkm} 39129088Smarkm 39229088Smarkm void 39329088Smarkmcfb64_session(key, server) 39429088Smarkm Session_Key *key; 39529088Smarkm int server; 39629088Smarkm{ 39729088Smarkm fb64_session(key, server, &fb[CFB]); 39829088Smarkm} 39929088Smarkm 40029088Smarkm void 40129088Smarkmofb64_session(key, server) 40229088Smarkm Session_Key *key; 40329088Smarkm int server; 40429088Smarkm{ 40529088Smarkm fb64_session(key, server, &fb[OFB]); 40629088Smarkm} 40729088Smarkm 40829088Smarkm static void 40929088Smarkmfb64_session(key, server, fbp) 41029088Smarkm Session_Key *key; 41129088Smarkm int server; 41229088Smarkm struct fb *fbp; 41329088Smarkm{ 41429088Smarkm 41529088Smarkm if (!key || key->type != SK_DES) { 41629088Smarkm if (encrypt_debug_mode) 41729088Smarkm printf("Can't set krbdes's session key (%d != %d)\r\n", 41829088Smarkm key ? key->type : -1, SK_DES); 41929088Smarkm return; 42029088Smarkm } 42129088Smarkm memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block)); 42229088Smarkm 42329088Smarkm fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); 42429088Smarkm fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); 42529088Smarkm 42629088Smarkm if (fbp->once == 0) { 42729181Smarkm des_set_random_generator_seed((Block *)fbp->krbdes_key); 42829088Smarkm fbp->once = 1; 42929088Smarkm } 43029181Smarkm des_key_sched((Block *)fbp->krbdes_key, fbp->krbdes_sched); 43129088Smarkm /* 43229088Smarkm * Now look to see if krbdes_start() was was waiting for 43329088Smarkm * the key to show up. If so, go ahead an call it now 43429088Smarkm * that we have the key. 43529088Smarkm */ 43629088Smarkm if (fbp->need_start) { 43729088Smarkm fbp->need_start = 0; 43829088Smarkm fb64_start(fbp, DIR_ENCRYPT, server); 43929088Smarkm } 44029088Smarkm} 44129088Smarkm 44229088Smarkm/* 44329088Smarkm * We only accept a keyid of 0. If we get a keyid of 44429088Smarkm * 0, then mark the state as SUCCESS. 44529088Smarkm */ 44629088Smarkm int 44729088Smarkmcfb64_keyid(dir, kp, lenp) 44829088Smarkm int dir, *lenp; 44929088Smarkm unsigned char *kp; 45029088Smarkm{ 45129088Smarkm return(fb64_keyid(dir, kp, lenp, &fb[CFB])); 45229088Smarkm} 45329088Smarkm 45429088Smarkm int 45529088Smarkmofb64_keyid(dir, kp, lenp) 45629088Smarkm int dir, *lenp; 45729088Smarkm unsigned char *kp; 45829088Smarkm{ 45929088Smarkm return(fb64_keyid(dir, kp, lenp, &fb[OFB])); 46029088Smarkm} 46129088Smarkm 46229088Smarkm int 46329088Smarkmfb64_keyid(dir, kp, lenp, fbp) 46429088Smarkm int dir, *lenp; 46529088Smarkm unsigned char *kp; 46629088Smarkm struct fb *fbp; 46729088Smarkm{ 46829088Smarkm register int state = fbp->state[dir-1]; 46929088Smarkm 47029088Smarkm if (*lenp != 1 || (*kp != '\0')) { 47129088Smarkm *lenp = 0; 47229088Smarkm return(state); 47329088Smarkm } 47429088Smarkm 47529088Smarkm if (state == FAILED) 47629088Smarkm state = IN_PROGRESS; 47729088Smarkm 47829088Smarkm state &= ~NO_KEYID; 47929088Smarkm 48029088Smarkm return(fbp->state[dir-1] = state); 48129088Smarkm} 48229088Smarkm 48329088Smarkm void 48429088Smarkmfb64_printsub(data, cnt, buf, buflen, type) 48529088Smarkm unsigned char *data, *buf, *type; 48629088Smarkm int cnt, buflen; 48729088Smarkm{ 48829088Smarkm char lbuf[32]; 48929088Smarkm register int i; 49029088Smarkm char *cp; 49129088Smarkm 49229088Smarkm buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 49329088Smarkm buflen -= 1; 49429088Smarkm 49529088Smarkm switch(data[2]) { 49629088Smarkm case FB64_IV: 49729088Smarkm sprintf(lbuf, "%s_IV", type); 49829088Smarkm cp = lbuf; 49929088Smarkm goto common; 50029088Smarkm 50129088Smarkm case FB64_IV_OK: 50229088Smarkm sprintf(lbuf, "%s_IV_OK", type); 50329088Smarkm cp = lbuf; 50429088Smarkm goto common; 50529088Smarkm 50629088Smarkm case FB64_IV_BAD: 50729088Smarkm sprintf(lbuf, "%s_IV_BAD", type); 50829088Smarkm cp = lbuf; 50929088Smarkm goto common; 51029088Smarkm 51129088Smarkm default: 51229088Smarkm sprintf(lbuf, " %d (unknown)", data[2]); 51329088Smarkm cp = lbuf; 51429088Smarkm common: 51529088Smarkm for (; (buflen > 0) && (*buf = *cp++); buf++) 51629088Smarkm buflen--; 51729088Smarkm for (i = 3; i < cnt; i++) { 51829088Smarkm sprintf(lbuf, " %d", data[i]); 51929088Smarkm for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) 52029088Smarkm buflen--; 52129088Smarkm } 52229088Smarkm break; 52329088Smarkm } 52429088Smarkm} 52529088Smarkm 52629088Smarkm void 52729088Smarkmcfb64_printsub(data, cnt, buf, buflen) 52829088Smarkm unsigned char *data, *buf; 52929088Smarkm int cnt, buflen; 53029088Smarkm{ 53129088Smarkm fb64_printsub(data, cnt, buf, buflen, "CFB64"); 53229088Smarkm} 53329088Smarkm 53429088Smarkm void 53529088Smarkmofb64_printsub(data, cnt, buf, buflen) 53629088Smarkm unsigned char *data, *buf; 53729088Smarkm int cnt, buflen; 53829088Smarkm{ 53929088Smarkm fb64_printsub(data, cnt, buf, buflen, "OFB64"); 54029088Smarkm} 54129088Smarkm 54229088Smarkm void 54329088Smarkmfb64_stream_iv(seed, stp) 54429088Smarkm Block seed; 54529088Smarkm register struct stinfo *stp; 54629088Smarkm{ 54729088Smarkm 54829088Smarkm memmove((void *)stp->str_iv, (void *)seed, sizeof(Block)); 54929088Smarkm memmove((void *)stp->str_output, (void *)seed, sizeof(Block)); 55029088Smarkm 55129181Smarkm des_key_sched((Block *)stp->str_ikey, stp->str_sched); 55229088Smarkm 55329088Smarkm stp->str_index = sizeof(Block); 55429088Smarkm} 55529088Smarkm 55629088Smarkm void 55729088Smarkmfb64_stream_key(key, stp) 55829088Smarkm Block key; 55929088Smarkm register struct stinfo *stp; 56029088Smarkm{ 56129088Smarkm memmove((void *)stp->str_ikey, (void *)key, sizeof(Block)); 56229181Smarkm des_key_sched((Block *)key, stp->str_sched); 56329088Smarkm 56429088Smarkm memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block)); 56529088Smarkm 56629088Smarkm stp->str_index = sizeof(Block); 56729088Smarkm} 56829088Smarkm 56929088Smarkm/* 57029088Smarkm * DES 64 bit Cipher Feedback 57129088Smarkm * 57229088Smarkm * key --->+-----+ 57329088Smarkm * +->| DES |--+ 57429088Smarkm * | +-----+ | 57529088Smarkm * | v 57629088Smarkm * INPUT --(--------->(+)+---> DATA 57729088Smarkm * | | 57829088Smarkm * +-------------+ 57929088Smarkm * 58029088Smarkm * 58129088Smarkm * Given: 58229088Smarkm * iV: Initial vector, 64 bits (8 bytes) long. 58329088Smarkm * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 58429088Smarkm * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 58529088Smarkm * 58629088Smarkm * V0 = DES(iV, key) 58729088Smarkm * On = Dn ^ Vn 58829088Smarkm * V(n+1) = DES(On, key) 58929088Smarkm */ 59029088Smarkm 59129088Smarkm void 59229088Smarkmcfb64_encrypt(s, c) 59329088Smarkm register unsigned char *s; 59429088Smarkm int c; 59529088Smarkm{ 59629088Smarkm register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; 59729088Smarkm register int index; 59829088Smarkm 59929088Smarkm index = stp->str_index; 60029088Smarkm while (c-- > 0) { 60129088Smarkm if (index == sizeof(Block)) { 60229088Smarkm Block b; 60329181Smarkm des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 60429088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 60529088Smarkm index = 0; 60629088Smarkm } 60729088Smarkm 60829088Smarkm /* On encryption, we store (feed ^ data) which is cypher */ 60929088Smarkm *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); 61029088Smarkm s++; 61129088Smarkm index++; 61229088Smarkm } 61329088Smarkm stp->str_index = index; 61429088Smarkm} 61529088Smarkm 61629088Smarkm int 61729088Smarkmcfb64_decrypt(data) 61829088Smarkm int data; 61929088Smarkm{ 62029088Smarkm register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; 62129088Smarkm int index; 62229088Smarkm 62329088Smarkm if (data == -1) { 62429088Smarkm /* 62529088Smarkm * Back up one byte. It is assumed that we will 62629088Smarkm * never back up more than one byte. If we do, this 62729088Smarkm * may or may not work. 62829088Smarkm */ 62929088Smarkm if (stp->str_index) 63029088Smarkm --stp->str_index; 63129088Smarkm return(0); 63229088Smarkm } 63329088Smarkm 63429088Smarkm index = stp->str_index++; 63529088Smarkm if (index == sizeof(Block)) { 63629088Smarkm Block b; 63729181Smarkm des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1); 63829088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 63929088Smarkm stp->str_index = 1; /* Next time will be 1 */ 64029088Smarkm index = 0; /* But now use 0 */ 64129088Smarkm } 64229088Smarkm 64329088Smarkm /* On decryption we store (data) which is cypher. */ 64429088Smarkm stp->str_output[index] = data; 64529088Smarkm return(data ^ stp->str_feed[index]); 64629088Smarkm} 64729088Smarkm 64829088Smarkm/* 64929088Smarkm * DES 64 bit Output Feedback 65029088Smarkm * 65129088Smarkm * key --->+-----+ 65229088Smarkm * +->| DES |--+ 65329088Smarkm * | +-----+ | 65429088Smarkm * +-----------+ 65529088Smarkm * v 65629088Smarkm * INPUT -------->(+) ----> DATA 65729088Smarkm * 65829088Smarkm * Given: 65929088Smarkm * iV: Initial vector, 64 bits (8 bytes) long. 66029088Smarkm * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). 66129088Smarkm * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. 66229088Smarkm * 66329088Smarkm * V0 = DES(iV, key) 66429088Smarkm * V(n+1) = DES(Vn, key) 66529088Smarkm * On = Dn ^ Vn 66629088Smarkm */ 66729088Smarkm void 66829088Smarkmofb64_encrypt(s, c) 66929088Smarkm register unsigned char *s; 67029088Smarkm int c; 67129088Smarkm{ 67229088Smarkm register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; 67329088Smarkm register int index; 67429088Smarkm 67529088Smarkm index = stp->str_index; 67629088Smarkm while (c-- > 0) { 67729088Smarkm if (index == sizeof(Block)) { 67829088Smarkm Block b; 67929181Smarkm des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 68029088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 68129088Smarkm index = 0; 68229088Smarkm } 68329088Smarkm *s++ ^= stp->str_feed[index]; 68429088Smarkm index++; 68529088Smarkm } 68629088Smarkm stp->str_index = index; 68729088Smarkm} 68829088Smarkm 68929088Smarkm int 69029088Smarkmofb64_decrypt(data) 69129088Smarkm int data; 69229088Smarkm{ 69329088Smarkm register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; 69429088Smarkm int index; 69529088Smarkm 69629088Smarkm if (data == -1) { 69729088Smarkm /* 69829088Smarkm * Back up one byte. It is assumed that we will 69929088Smarkm * never back up more than one byte. If we do, this 70029088Smarkm * may or may not work. 70129088Smarkm */ 70229088Smarkm if (stp->str_index) 70329088Smarkm --stp->str_index; 70429088Smarkm return(0); 70529088Smarkm } 70629088Smarkm 70729088Smarkm index = stp->str_index++; 70829088Smarkm if (index == sizeof(Block)) { 70929088Smarkm Block b; 71029181Smarkm des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1); 71129088Smarkm memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); 71229088Smarkm stp->str_index = 1; /* Next time will be 1 */ 71329088Smarkm index = 0; /* But now use 0 */ 71429088Smarkm } 71529088Smarkm 71629088Smarkm return(data ^ stp->str_feed[index]); 71729088Smarkm} 71829088Smarkm# endif /* DES_ENCRYPTION */ 71929088Smarkm# endif /* AUTHENTICATION */ 72029088Smarkm#endif /* ENCRYPTION */ 721