[BACK]Return to enc_des.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / telnet

Annotation of src/usr.bin/telnet/enc_des.c, Revision 1.1

1.1     ! deraadt     1: /*     $OpenBSD: enc_des.c,v 1.2 2003/06/02 19:38:25 millert Exp $ */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1991, 1993
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. Neither the name of the University nor the names of its contributors
        !            16:  *    may be used to endorse or promote products derived from this software
        !            17:  *    without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  */
        !            31:
        !            32: /* $KTH: enc_des.c,v 1.16 1998/07/09 23:16:23 assar Exp $ */
        !            33:
        !            34: #if    defined(AUTHENTICATION) && defined(ENCRYPTION) && defined(DES_ENCRYPTION)
        !            35: #include <arpa/telnet.h>
        !            36: #include <stdio.h>
        !            37: #include <stdlib.h>
        !            38: #include <string.h>
        !            39:
        !            40: #include "encrypt.h"
        !            41: #include "misc-proto.h"
        !            42: #include <des.h>
        !            43:
        !            44: extern int encrypt_debug_mode;
        !            45:
        !            46: #define        CFB     0
        !            47: #define        OFB     1
        !            48:
        !            49: #define        NO_SEND_IV      1
        !            50: #define        NO_RECV_IV      2
        !            51: #define        NO_KEYID        4
        !            52: #define        IN_PROGRESS     (NO_SEND_IV|NO_RECV_IV|NO_KEYID)
        !            53: #define        SUCCESS         0
        !            54: #define        FAILED          -1
        !            55:
        !            56:
        !            57: struct stinfo {
        !            58:   des_cblock   str_output;
        !            59:   des_cblock   str_feed;
        !            60:   des_cblock   str_iv;
        !            61:   des_cblock   str_ikey;
        !            62:   des_key_schedule str_sched;
        !            63:   int          str_index;
        !            64:   int          str_flagshift;
        !            65: };
        !            66:
        !            67: struct fb {
        !            68:        des_cblock krbdes_key;
        !            69:        des_key_schedule krbdes_sched;
        !            70:        des_cblock temp_feed;
        !            71:        unsigned char fb_feed[64];
        !            72:        int need_start;
        !            73:        int state[2];
        !            74:        int keyid[2];
        !            75:        int once;
        !            76:        struct stinfo streams[2];
        !            77: };
        !            78:
        !            79: static struct fb fb[2];
        !            80:
        !            81: struct keyidlist {
        !            82:        char    *keyid;
        !            83:        int     keyidlen;
        !            84:        char    *key;
        !            85:        int     keylen;
        !            86:        int     flags;
        !            87: } keyidlist [] = {
        !            88:        { "\0", 1, 0, 0, 0 },           /* default key of zero */
        !            89:        { 0, 0, 0, 0, 0 }
        !            90: };
        !            91:
        !            92: #define        KEYFLAG_MASK    03
        !            93:
        !            94: #define        KEYFLAG_NOINIT  00
        !            95: #define        KEYFLAG_INIT    01
        !            96: #define        KEYFLAG_OK      02
        !            97: #define        KEYFLAG_BAD     03
        !            98:
        !            99: #define        KEYFLAG_SHIFT   2
        !           100:
        !           101: #define        SHIFT_VAL(a,b)  (KEYFLAG_SHIFT*((a)+((b)*2)))
        !           102:
        !           103: #define        FB64_IV         1
        !           104: #define        FB64_IV_OK      2
        !           105: #define        FB64_IV_BAD     3
        !           106:
        !           107:
        !           108: void fb64_stream_iv (des_cblock, struct stinfo *);
        !           109: void fb64_init (struct fb *);
        !           110: static int fb64_start (struct fb *, int, int);
        !           111: int fb64_is (unsigned char *, int, struct fb *);
        !           112: int fb64_reply (unsigned char *, int, struct fb *);
        !           113: static void fb64_session (Session_Key *, int, struct fb *);
        !           114: void fb64_stream_key (des_cblock, struct stinfo *);
        !           115: int fb64_keyid (int, unsigned char *, int *, struct fb *);
        !           116:
        !           117: void cfb64_init(int server)
        !           118: {
        !           119:        fb64_init(&fb[CFB]);
        !           120:        fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
        !           121:        fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
        !           122:        fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
        !           123: }
        !           124:
        !           125:
        !           126: void ofb64_init(int server)
        !           127: {
        !           128:        fb64_init(&fb[OFB]);
        !           129:        fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
        !           130:        fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
        !           131:        fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
        !           132: }
        !           133:
        !           134: void fb64_init(struct fb *fbp)
        !           135: {
        !           136:        memset(fbp,0, sizeof(*fbp));
        !           137:        fbp->state[0] = fbp->state[1] = FAILED;
        !           138:        fbp->fb_feed[0] = IAC;
        !           139:        fbp->fb_feed[1] = SB;
        !           140:        fbp->fb_feed[2] = TELOPT_ENCRYPT;
        !           141:        fbp->fb_feed[3] = ENCRYPT_IS;
        !           142: }
        !           143:
        !           144: /*
        !           145:  * Returns:
        !           146:  *     -1: some error.  Negotiation is done, encryption not ready.
        !           147:  *      0: Successful, initial negotiation all done.
        !           148:  *      1: successful, negotiation not done yet.
        !           149:  *      2: Not yet.  Other things (like getting the key from
        !           150:  *         Kerberos) have to happen before we can continue.
        !           151:  */
        !           152: int cfb64_start(int dir, int server)
        !           153: {
        !           154:        return(fb64_start(&fb[CFB], dir, server));
        !           155: }
        !           156:
        !           157: int ofb64_start(int dir, int server)
        !           158: {
        !           159:        return(fb64_start(&fb[OFB], dir, server));
        !           160: }
        !           161:
        !           162: static int fb64_start(struct fb *fbp, int dir, int server)
        !           163: {
        !           164:        int x;
        !           165:        unsigned char *p;
        !           166:        int state;
        !           167:
        !           168:        switch (dir) {
        !           169:        case DIR_DECRYPT:
        !           170:                /*
        !           171:                 * This is simply a request to have the other side
        !           172:                 * start output (our input).  He will negotiate an
        !           173:                 * IV so we need not look for it.
        !           174:                 */
        !           175:                state = fbp->state[dir-1];
        !           176:                if (state == FAILED)
        !           177:                        state = IN_PROGRESS;
        !           178:                break;
        !           179:
        !           180:        case DIR_ENCRYPT:
        !           181:                state = fbp->state[dir-1];
        !           182:                if (state == FAILED)
        !           183:                        state = IN_PROGRESS;
        !           184:                else if ((state & NO_SEND_IV) == 0) {
        !           185:                        break;
        !           186:                }
        !           187:
        !           188:                if (!VALIDKEY(fbp->krbdes_key)) {
        !           189:                        fbp->need_start = 1;
        !           190:                        break;
        !           191:                }
        !           192:
        !           193:                state &= ~NO_SEND_IV;
        !           194:                state |= NO_RECV_IV;
        !           195:                if (encrypt_debug_mode)
        !           196:                        printf("Creating new feed\r\n");
        !           197:                /*
        !           198:                 * Create a random feed and send it over.
        !           199:                 */
        !           200: #ifndef OLD_DES_RANDOM_KEY
        !           201:                des_new_random_key(&fbp->temp_feed);
        !           202: #else
        !           203:                /*
        !           204:                 * From des_cryp.man "If the des_check_key flag is non-zero,
        !           205:                 *  des_set_key will check that the key passed is
        !           206:                 *  of odd parity and is not a week or semi-weak key."
        !           207:                 */
        !           208:                do {
        !           209:                        des_random_key(fbp->temp_feed);
        !           210:                        des_set_odd_parity(fbp->temp_feed);
        !           211:                } while (des_is_weak_key(fbp->temp_feed));
        !           212: #endif
        !           213:                des_ecb_encrypt(&fbp->temp_feed,
        !           214:                                &fbp->temp_feed,
        !           215:                                fbp->krbdes_sched, 1);
        !           216:                p = fbp->fb_feed + 3;
        !           217:                *p++ = ENCRYPT_IS;
        !           218:                p++;
        !           219:                *p++ = FB64_IV;
        !           220:                for (x = 0; x < sizeof(des_cblock); ++x) {
        !           221:                        if ((*p++ = fbp->temp_feed[x]) == IAC)
        !           222:                                *p++ = IAC;
        !           223:                }
        !           224:                *p++ = IAC;
        !           225:                *p++ = SE;
        !           226:                printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
        !           227:                telnet_net_write(fbp->fb_feed, p - fbp->fb_feed);
        !           228:                break;
        !           229:        default:
        !           230:                return(FAILED);
        !           231:        }
        !           232:        return(fbp->state[dir-1] = state);
        !           233: }
        !           234:
        !           235: /*
        !           236:  * Returns:
        !           237:  *     -1: some error.  Negotiation is done, encryption not ready.
        !           238:  *      0: Successful, initial negotiation all done.
        !           239:  *      1: successful, negotiation not done yet.
        !           240:  */
        !           241:
        !           242: int cfb64_is(unsigned char *data, int cnt)
        !           243: {
        !           244:        return(fb64_is(data, cnt, &fb[CFB]));
        !           245: }
        !           246:
        !           247: int ofb64_is(unsigned char *data, int cnt)
        !           248: {
        !           249:        return(fb64_is(data, cnt, &fb[OFB]));
        !           250: }
        !           251:
        !           252:
        !           253: int fb64_is(unsigned char *data, int cnt, struct fb *fbp)
        !           254: {
        !           255:        unsigned char *p;
        !           256:        int state = fbp->state[DIR_DECRYPT-1];
        !           257:
        !           258:        if (cnt-- < 1)
        !           259:                goto failure;
        !           260:
        !           261:        switch (*data++) {
        !           262:        case FB64_IV:
        !           263:                if (cnt != sizeof(des_cblock)) {
        !           264:                        if (encrypt_debug_mode)
        !           265:                                printf("CFB64: initial vector failed on size\r\n");
        !           266:                        state = FAILED;
        !           267:                        goto failure;
        !           268:                }
        !           269:
        !           270:                if (encrypt_debug_mode)
        !           271:                        printf("CFB64: initial vector received\r\n");
        !           272:
        !           273:                if (encrypt_debug_mode)
        !           274:                        printf("Initializing Decrypt stream\r\n");
        !           275:
        !           276:                fb64_stream_iv(data, &fbp->streams[DIR_DECRYPT-1]);
        !           277:
        !           278:                p = fbp->fb_feed + 3;
        !           279:                *p++ = ENCRYPT_REPLY;
        !           280:                p++;
        !           281:                *p++ = FB64_IV_OK;
        !           282:                *p++ = IAC;
        !           283:                *p++ = SE;
        !           284:                printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
        !           285:                telnet_net_write(fbp->fb_feed, p - fbp->fb_feed);
        !           286:
        !           287:                state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
        !           288:                break;
        !           289:
        !           290:        default:
        !           291:                if (encrypt_debug_mode) {
        !           292:                        printf("Unknown option type: %d\r\n", *(data-1));
        !           293:                        printd(data, cnt);
        !           294:                        printf("\r\n");
        !           295:                }
        !           296:                /* FALL THROUGH */
        !           297:        failure:
        !           298:                /*
        !           299:                 * We failed.  Send an FB64_IV_BAD option
        !           300:                 * to the other side so it will know that
        !           301:                 * things failed.
        !           302:                 */
        !           303:                p = fbp->fb_feed + 3;
        !           304:                *p++ = ENCRYPT_REPLY;
        !           305:                p++;
        !           306:                *p++ = FB64_IV_BAD;
        !           307:                *p++ = IAC;
        !           308:                *p++ = SE;
        !           309:                printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
        !           310:                telnet_net_write(fbp->fb_feed, p - fbp->fb_feed);
        !           311:
        !           312:                break;
        !           313:        }
        !           314:        return(fbp->state[DIR_DECRYPT-1] = state);
        !           315: }
        !           316:
        !           317: /*
        !           318:  * Returns:
        !           319:  *     -1: some error.  Negotiation is done, encryption not ready.
        !           320:  *      0: Successful, initial negotiation all done.
        !           321:  *      1: successful, negotiation not done yet.
        !           322:  */
        !           323:
        !           324: int cfb64_reply(unsigned char *data, int cnt)
        !           325: {
        !           326:        return(fb64_reply(data, cnt, &fb[CFB]));
        !           327: }
        !           328:
        !           329: int ofb64_reply(unsigned char *data, int cnt)
        !           330: {
        !           331:        return(fb64_reply(data, cnt, &fb[OFB]));
        !           332: }
        !           333:
        !           334:
        !           335: int fb64_reply(unsigned char *data, int cnt, struct fb *fbp)
        !           336: {
        !           337:        int state = fbp->state[DIR_ENCRYPT-1];
        !           338:
        !           339:        if (cnt-- < 1)
        !           340:                goto failure;
        !           341:
        !           342:        switch (*data++) {
        !           343:        case FB64_IV_OK:
        !           344:                fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
        !           345:                if (state == FAILED)
        !           346:                        state = IN_PROGRESS;
        !           347:                state &= ~NO_RECV_IV;
        !           348:                encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1);
        !           349:                break;
        !           350:
        !           351:        case FB64_IV_BAD:
        !           352:                memset(fbp->temp_feed, 0, sizeof(des_cblock));
        !           353:                fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
        !           354:                state = FAILED;
        !           355:                break;
        !           356:
        !           357:        default:
        !           358:                if (encrypt_debug_mode) {
        !           359:                        printf("Unknown option type: %d\r\n", data[-1]);
        !           360:                        printd(data, cnt);
        !           361:                        printf("\r\n");
        !           362:                }
        !           363:                /* FALL THROUGH */
        !           364:        failure:
        !           365:                state = FAILED;
        !           366:                break;
        !           367:        }
        !           368:        return(fbp->state[DIR_ENCRYPT-1] = state);
        !           369: }
        !           370:
        !           371: void cfb64_session(Session_Key *key, int server)
        !           372: {
        !           373:        fb64_session(key, server, &fb[CFB]);
        !           374: }
        !           375:
        !           376: void ofb64_session(Session_Key *key, int server)
        !           377: {
        !           378:        fb64_session(key, server, &fb[OFB]);
        !           379: }
        !           380:
        !           381: static void fb64_session(Session_Key *key, int server, struct fb *fbp)
        !           382: {
        !           383:
        !           384:        if (!key || key->type != SK_DES) {
        !           385:                if (encrypt_debug_mode)
        !           386:                        printf("Can't set krbdes's session key (%d != %d)\r\n",
        !           387:                                key ? key->type : -1, SK_DES);
        !           388:                return;
        !           389:        }
        !           390:        memcpy(fbp->krbdes_key, key->data, sizeof(des_cblock));
        !           391:
        !           392:        fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
        !           393:        fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
        !           394:
        !           395:        if (fbp->once == 0) {
        !           396: #ifndef OLD_DES_RANDOM_KEY
        !           397:                des_init_random_number_generator(&fbp->krbdes_key);
        !           398: #endif
        !           399:                fbp->once = 1;
        !           400:        }
        !           401:        des_key_sched(&fbp->krbdes_key, fbp->krbdes_sched);
        !           402:        /*
        !           403:         * Now look to see if krbdes_start() was was waiting for
        !           404:         * the key to show up.  If so, go ahead an call it now
        !           405:         * that we have the key.
        !           406:         */
        !           407:        if (fbp->need_start) {
        !           408:                fbp->need_start = 0;
        !           409:                fb64_start(fbp, DIR_ENCRYPT, server);
        !           410:        }
        !           411: }
        !           412:
        !           413: /*
        !           414:  * We only accept a keyid of 0.  If we get a keyid of
        !           415:  * 0, then mark the state as SUCCESS.
        !           416:  */
        !           417:
        !           418: int cfb64_keyid(int dir, unsigned char *kp, int *lenp)
        !           419: {
        !           420:        return(fb64_keyid(dir, kp, lenp, &fb[CFB]));
        !           421: }
        !           422:
        !           423: int ofb64_keyid(int dir, unsigned char *kp, int *lenp)
        !           424: {
        !           425:        return(fb64_keyid(dir, kp, lenp, &fb[OFB]));
        !           426: }
        !           427:
        !           428: int fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp)
        !           429: {
        !           430:        int state = fbp->state[dir-1];
        !           431:
        !           432:        if (*lenp != 1 || (*kp != '\0')) {
        !           433:                *lenp = 0;
        !           434:                return(state);
        !           435:        }
        !           436:
        !           437:        if (state == FAILED)
        !           438:                state = IN_PROGRESS;
        !           439:
        !           440:        state &= ~NO_KEYID;
        !           441:
        !           442:        return(fbp->state[dir-1] = state);
        !           443: }
        !           444:
        !           445: void fb64_printsub(unsigned char *data, int cnt,
        !           446:                   unsigned char *buf, int buflen, char *type)
        !           447: {
        !           448:        char lbuf[32];
        !           449:        int i;
        !           450:        char *cp;
        !           451:
        !           452:        buf[buflen-1] = '\0';           /* make sure it's NULL terminated */
        !           453:        buflen -= 1;
        !           454:
        !           455:        switch(data[2]) {
        !           456:        case FB64_IV:
        !           457:                snprintf(lbuf, sizeof(lbuf), "%s_IV", type);
        !           458:                cp = lbuf;
        !           459:                goto common;
        !           460:
        !           461:        case FB64_IV_OK:
        !           462:                snprintf(lbuf, sizeof(lbuf), "%s_IV_OK", type);
        !           463:                cp = lbuf;
        !           464:                goto common;
        !           465:
        !           466:        case FB64_IV_BAD:
        !           467:                snprintf(lbuf, sizeof(lbuf), "%s_IV_BAD", type);
        !           468:                cp = lbuf;
        !           469:                goto common;
        !           470:
        !           471:        default:
        !           472:                snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[2]);
        !           473:                cp = lbuf;
        !           474:        common:
        !           475:                for (; (buflen > 0) && (*buf = *cp++); buf++)
        !           476:                        buflen--;
        !           477:                for (i = 3; i < cnt; i++) {
        !           478:                        snprintf(lbuf, sizeof(lbuf), " %d", data[i]);
        !           479:                        for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
        !           480:                                buflen--;
        !           481:                }
        !           482:                break;
        !           483:        }
        !           484: }
        !           485:
        !           486: void cfb64_printsub(unsigned char *data, int cnt,
        !           487:                    unsigned char *buf, int buflen)
        !           488: {
        !           489:        fb64_printsub(data, cnt, buf, buflen, "CFB64");
        !           490: }
        !           491:
        !           492: void ofb64_printsub(unsigned char *data, int cnt,
        !           493:                    unsigned char *buf, int buflen)
        !           494: {
        !           495:        fb64_printsub(data, cnt, buf, buflen, "OFB64");
        !           496: }
        !           497:
        !           498: void fb64_stream_iv(des_cblock seed, struct stinfo *stp)
        !           499: {
        !           500:
        !           501:        memcpy(stp->str_iv, seed,sizeof(des_cblock));
        !           502:        memcpy(stp->str_output, seed, sizeof(des_cblock));
        !           503:
        !           504:        des_key_sched(&stp->str_ikey, stp->str_sched);
        !           505:
        !           506:        stp->str_index = sizeof(des_cblock);
        !           507: }
        !           508:
        !           509: void fb64_stream_key(des_cblock key, struct stinfo *stp)
        !           510: {
        !           511:        memcpy(stp->str_ikey, key, sizeof(des_cblock));
        !           512:        des_key_sched((des_cblock*)key, stp->str_sched);
        !           513:
        !           514:        memcpy(stp->str_output, stp->str_iv, sizeof(des_cblock));
        !           515:
        !           516:        stp->str_index = sizeof(des_cblock);
        !           517: }
        !           518:
        !           519: /*
        !           520:  * DES 64 bit Cipher Feedback
        !           521:  *
        !           522:  *     key --->+-----+
        !           523:  *          +->| DES |--+
        !           524:  *          |  +-----+  |
        !           525:  *         |           v
        !           526:  *  INPUT --(--------->(+)+---> DATA
        !           527:  *          |             |
        !           528:  *         +-------------+
        !           529:  *
        !           530:  *
        !           531:  * Given:
        !           532:  *     iV: Initial vector, 64 bits (8 bytes) long.
        !           533:  *     Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
        !           534:  *     On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
        !           535:  *
        !           536:  *     V0 = DES(iV, key)
        !           537:  *     On = Dn ^ Vn
        !           538:  *     V(n+1) = DES(On, key)
        !           539:  */
        !           540:
        !           541: void cfb64_encrypt(unsigned char *s, int c)
        !           542: {
        !           543:        struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1];
        !           544:        int index;
        !           545:
        !           546:        index = stp->str_index;
        !           547:        while (c-- > 0) {
        !           548:                if (index == sizeof(des_cblock)) {
        !           549:                        des_cblock b;
        !           550:                        des_ecb_encrypt(&stp->str_output, &b,stp->str_sched, 1);
        !           551:                        memcpy(stp->str_feed, b, sizeof(des_cblock));
        !           552:                        index = 0;
        !           553:                }
        !           554:
        !           555:                /* On encryption, we store (feed ^ data) which is cypher */
        !           556:                *s = stp->str_output[index] = (stp->str_feed[index] ^ *s);
        !           557:                s++;
        !           558:                index++;
        !           559:        }
        !           560:        stp->str_index = index;
        !           561: }
        !           562:
        !           563: int cfb64_decrypt(int data)
        !           564: {
        !           565:        struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
        !           566:        int index;
        !           567:
        !           568:        if (data == -1) {
        !           569:                /*
        !           570:                 * Back up one byte.  It is assumed that we will
        !           571:                 * never back up more than one byte.  If we do, this
        !           572:                 * may or may not work.
        !           573:                 */
        !           574:                if (stp->str_index)
        !           575:                        --stp->str_index;
        !           576:                return(0);
        !           577:        }
        !           578:
        !           579:        index = stp->str_index++;
        !           580:        if (index == sizeof(des_cblock)) {
        !           581:                des_cblock b;
        !           582:                des_ecb_encrypt(&stp->str_output,&b, stp->str_sched, 1);
        !           583:                memcpy(stp->str_feed, b, sizeof(des_cblock));
        !           584:                stp->str_index = 1;     /* Next time will be 1 */
        !           585:                index = 0;              /* But now use 0 */
        !           586:        }
        !           587:
        !           588:        /* On decryption we store (data) which is cypher. */
        !           589:        stp->str_output[index] = data;
        !           590:        return(data ^ stp->str_feed[index]);
        !           591: }
        !           592:
        !           593: /*
        !           594:  * DES 64 bit Output Feedback
        !           595:  *
        !           596:  * key --->+-----+
        !           597:  *     +->| DES |--+
        !           598:  *     |  +-----+  |
        !           599:  *     +-----------+
        !           600:  *                 v
        !           601:  *  INPUT -------->(+) ----> DATA
        !           602:  *
        !           603:  * Given:
        !           604:  *     iV: Initial vector, 64 bits (8 bytes) long.
        !           605:  *     Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
        !           606:  *     On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
        !           607:  *
        !           608:  *     V0 = DES(iV, key)
        !           609:  *     V(n+1) = DES(Vn, key)
        !           610:  *     On = Dn ^ Vn
        !           611:  */
        !           612:
        !           613: void ofb64_encrypt(unsigned char *s, int c)
        !           614: {
        !           615:        struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1];
        !           616:        int index;
        !           617:
        !           618:        index = stp->str_index;
        !           619:        while (c-- > 0) {
        !           620:                if (index == sizeof(des_cblock)) {
        !           621:                        des_cblock b;
        !           622:                        des_ecb_encrypt(&stp->str_feed,&b, stp->str_sched, 1);
        !           623:                        memcpy(stp->str_feed, b, sizeof(des_cblock));
        !           624:                        index = 0;
        !           625:                }
        !           626:                *s++ ^= stp->str_feed[index];
        !           627:                index++;
        !           628:        }
        !           629:        stp->str_index = index;
        !           630: }
        !           631:
        !           632: int ofb64_decrypt(int data)
        !           633: {
        !           634:        struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
        !           635:        int index;
        !           636:
        !           637:        if (data == -1) {
        !           638:                /*
        !           639:                 * Back up one byte.  It is assumed that we will
        !           640:                 * never back up more than one byte.  If we do, this
        !           641:                 * may or may not work.
        !           642:                 */
        !           643:                if (stp->str_index)
        !           644:                        --stp->str_index;
        !           645:                return(0);
        !           646:        }
        !           647:
        !           648:        index = stp->str_index++;
        !           649:        if (index == sizeof(des_cblock)) {
        !           650:                des_cblock b;
        !           651:                des_ecb_encrypt(&stp->str_feed,&b,stp->str_sched, 1);
        !           652:                memcpy(stp->str_feed, b, sizeof(des_cblock));
        !           653:                stp->str_index = 1;     /* Next time will be 1 */
        !           654:                index = 0;              /* But now use 0 */
        !           655:        }
        !           656:
        !           657:        return(data ^ stp->str_feed[index]);
        !           658: }
        !           659: #endif
        !           660: