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