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