home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / libtelnet / enc_des.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-23  |  15.5 KB  |  732 lines

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