home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnunet10.zip / source / libtelnet / enc_des.c < prev    next >
C/C++ Source or Header  |  1996-02-12  |  16KB  |  725 lines

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