1*f8570f8aSmrg /* $NetBSD: cbc.c,v 1.26 2023/08/01 07:04:14 mrg Exp $ */
249f0ad86Scgd
39b082a69Scgd /* cbc.c: This file contains the encryption routines for the ed line editor */
49b082a69Scgd /*-
5ba4d688dSalm * Copyright (c) 1993 The Regents of the University of California.
69b082a69Scgd * All rights reserved.
79b082a69Scgd *
8b5b29542Sagc * Redistribution and use in source and binary forms, with or without
9b5b29542Sagc * modification, are permitted provided that the following conditions
10b5b29542Sagc * are met:
11b5b29542Sagc * 1. Redistributions of source code must retain the above copyright
12b5b29542Sagc * notice, this list of conditions and the following disclaimer.
13b5b29542Sagc * 2. Redistributions in binary form must reproduce the above copyright
14b5b29542Sagc * notice, this list of conditions and the following disclaimer in the
15b5b29542Sagc * documentation and/or other materials provided with the distribution.
16b5b29542Sagc * 3. Neither the name of the University nor the names of its contributors
17b5b29542Sagc * may be used to endorse or promote products derived from this software
18b5b29542Sagc * without specific prior written permission.
19b5b29542Sagc *
20b5b29542Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21b5b29542Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22b5b29542Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23b5b29542Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24b5b29542Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25b5b29542Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26b5b29542Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27b5b29542Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28b5b29542Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29b5b29542Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30b5b29542Sagc * SUCH DAMAGE.
31b5b29542Sagc *
32b5b29542Sagc * from: @(#)bdes.c 5.5 (Berkeley) 6/27/91
33b5b29542Sagc */
34b5b29542Sagc
35b5b29542Sagc /*-
36ba4d688dSalm * Copyright (c) 1993 Andrew Moore, Talke Studio.
37ba4d688dSalm * All rights reserved.
389b082a69Scgd *
399b082a69Scgd * Redistribution and use in source and binary forms, with or without
409b082a69Scgd * modification, are permitted provided that the following conditions
419b082a69Scgd * are met:
429b082a69Scgd * 1. Redistributions of source code must retain the above copyright
439b082a69Scgd * notice, this list of conditions and the following disclaimer.
449b082a69Scgd * 2. Redistributions in binary form must reproduce the above copyright
459b082a69Scgd * notice, this list of conditions and the following disclaimer in the
469b082a69Scgd * documentation and/or other materials provided with the distribution.
479b082a69Scgd * 3. All advertising materials mentioning features or use of this software
489b082a69Scgd * must display the following acknowledgement:
499b082a69Scgd * This product includes software developed by the University of
509b082a69Scgd * California, Berkeley and its contributors.
519b082a69Scgd * 4. Neither the name of the University nor the names of its contributors
529b082a69Scgd * may be used to endorse or promote products derived from this software
539b082a69Scgd * without specific prior written permission.
549b082a69Scgd *
559b082a69Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
569b082a69Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
579b082a69Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
589b082a69Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
599b082a69Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
609b082a69Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
619b082a69Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
629b082a69Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
639b082a69Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
649b082a69Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
659b082a69Scgd * SUCH DAMAGE.
66ba4d688dSalm *
67ba4d688dSalm * from: @(#)bdes.c 5.5 (Berkeley) 6/27/91
689b082a69Scgd */
699b082a69Scgd
708b7ade1aSthorpej #include <sys/cdefs.h>
719b082a69Scgd #ifndef lint
7249f0ad86Scgd #if 0
731357f155Salm static char *rcsid = "@(#)cbc.c,v 1.2 1994/02/01 00:34:36 alm Exp";
7449f0ad86Scgd #else
75*f8570f8aSmrg __RCSID("$NetBSD: cbc.c,v 1.26 2023/08/01 07:04:14 mrg Exp $");
7649f0ad86Scgd #endif
779b082a69Scgd #endif /* not lint */
789b082a69Scgd
791357f155Salm #include <sys/types.h>
801357f155Salm #include <ctype.h>
819b082a69Scgd #include <errno.h>
829b082a69Scgd #include <pwd.h>
8375a6e035Sperry #ifdef DES
8475a6e035Sperry #include <time.h>
8575a6e035Sperry #endif
869b082a69Scgd
87f30a0860Salm #include "ed.h"
88f30a0860Salm
891357f155Salm
909b082a69Scgd /*
919b082a69Scgd * Define a divisor for rand() that yields a uniform distribution in the
929b082a69Scgd * range 0-255.
939b082a69Scgd */
949b082a69Scgd #define RAND_DIV (((unsigned) RAND_MAX + 1) >> 8)
959b082a69Scgd
969b082a69Scgd /*
979b082a69Scgd * BSD and System V systems offer special library calls that do
989380925bSalm * block move_liness and fills, so if possible we take advantage of them
999b082a69Scgd */
1002621a68cSalm #define MEMCPY(dest,src,len) memcpy((dest),(src),(len))
1012621a68cSalm #define MEMZERO(dest,len) memset((dest), 0, (len))
1029b082a69Scgd
1039b082a69Scgd /* Hide the calls to the primitive encryption routines. */
1049b082a69Scgd #define DES_KEY(buf) \
1059b082a69Scgd if (des_setkey(buf)) \
1069380925bSalm des_error("des_setkey");
1079b082a69Scgd #define DES_XFORM(buf) \
1089b082a69Scgd if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
1099380925bSalm des_error("des_cipher");
1109b082a69Scgd
1119b082a69Scgd /*
1129b082a69Scgd * read/write - no error checking
1139b082a69Scgd */
1149b082a69Scgd #define READ(buf, n, fp) fread(buf, sizeof(char), n, fp)
1159b082a69Scgd #define WRITE(buf, n, fp) fwrite(buf, sizeof(char), n, fp)
1169b082a69Scgd
1179b082a69Scgd /*
1189b082a69Scgd * some things to make references easier
1199b082a69Scgd */
1209b082a69Scgd typedef char Desbuf[8];
1219b082a69Scgd #define CHAR(x,i) (x[i])
1229b082a69Scgd #define UCHAR(x,i) (x[i])
1239b082a69Scgd #define BUFFER(x) (x)
1249b082a69Scgd #define UBUFFER(x) (x)
1259b082a69Scgd
126a36f9be1Smycroft #ifdef DES
1279b082a69Scgd /*
1289b082a69Scgd * global variables and related macros
1299b082a69Scgd */
1309b082a69Scgd
13185d0adbcSdholland static Desbuf ivec; /* initialization vector */
13285d0adbcSdholland static Desbuf pvec; /* padding vector */
13385d0adbcSdholland static char bits[] = { /* used to extract bits from a char */
1349b082a69Scgd '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
1359b082a69Scgd };
13685d0adbcSdholland static int pflag; /* 1 to preserve parity bits */
1379b082a69Scgd
13885d0adbcSdholland static char des_buf[8]; /* shared buffer for get_des_char/put_des_char */
13985d0adbcSdholland static int des_ct = 0; /* count for get_des_char/put_des_char */
14085d0adbcSdholland static int des_n = 0; /* index for put_des_char/get_des_char */
141a36f9be1Smycroft #endif
1422621a68cSalm
1432621a68cSalm
144a9adb2c9Sriz #ifdef DES
14585d0adbcSdholland static void des_error(const char *);
14685d0adbcSdholland static int hex_to_binary(int, int);
14785d0adbcSdholland static void expand_des_key(char *, char *);
148*f8570f8aSmrg static void set_des_key(Desbuf);
14985d0adbcSdholland static int cbc_decode(char *, FILE *);
15085d0adbcSdholland static int cbc_encode(char *, int, FILE *);
151a9adb2c9Sriz #endif
15285d0adbcSdholland
15385d0adbcSdholland
1549380925bSalm /* init_des_cipher: initialize DES */
1559b082a69Scgd void
init_des_cipher(void)156d33a7206Sxtraeme init_des_cipher(void)
1579b082a69Scgd {
1582621a68cSalm #ifdef DES
1599b082a69Scgd int i;
1609b082a69Scgd
1612621a68cSalm des_ct = des_n = 0;
1622621a68cSalm
163bbbbcbe4Swiz /* initialize the initialization vector */
1649b082a69Scgd MEMZERO(ivec, 8);
1659b082a69Scgd
16632cded6cSdholland /* initialize the padding vector */
1679b082a69Scgd srand((unsigned) time((time_t *) 0));
1689b082a69Scgd for (i = 0; i < 8; i++)
1699b082a69Scgd CHAR(pvec, i) = (char) (rand()/RAND_DIV);
1702621a68cSalm #endif
1719b082a69Scgd }
1729b082a69Scgd
1732621a68cSalm
1749380925bSalm /* get_des_char: return next char in an encrypted file */
1759380925bSalm int
get_des_char(FILE * fp)176d33a7206Sxtraeme get_des_char(FILE *fp)
1772621a68cSalm {
1782621a68cSalm #ifdef DES
1792621a68cSalm if (des_n >= des_ct) {
1802621a68cSalm des_n = 0;
1819380925bSalm des_ct = cbc_decode(des_buf, fp);
1822621a68cSalm }
183aa92b1b9Sdholland return (des_ct > 0) ? (unsigned char) des_buf[des_n++] : EOF;
1848b7ade1aSthorpej #else
1858b7ade1aSthorpej return EOF;
1862621a68cSalm #endif
1872621a68cSalm }
1882621a68cSalm
1892621a68cSalm
1909380925bSalm /* put_des_char: write a char to an encrypted file; return char written */
1919380925bSalm int
put_des_char(int c,FILE * fp)192d33a7206Sxtraeme put_des_char(int c, FILE *fp)
1932621a68cSalm {
1942621a68cSalm #ifdef DES
1952621a68cSalm if (des_n == sizeof des_buf) {
1969380925bSalm des_ct = cbc_encode(des_buf, des_n, fp);
1972621a68cSalm des_n = 0;
1982621a68cSalm }
199aa92b1b9Sdholland return (des_ct >= 0) ? (unsigned char) (des_buf[des_n++] = c) : EOF;
2008b7ade1aSthorpej #else
2018b7ade1aSthorpej return EOF;
2022621a68cSalm #endif
2032621a68cSalm }
2042621a68cSalm
2052621a68cSalm
2069380925bSalm /* flush_des_file: flush an encrypted file's output; return status */
2079380925bSalm int
flush_des_file(FILE * fp)208d33a7206Sxtraeme flush_des_file(FILE *fp)
2092621a68cSalm {
2102621a68cSalm #ifdef DES
2112621a68cSalm if (des_n == sizeof des_buf) {
2129380925bSalm des_ct = cbc_encode(des_buf, des_n, fp);
2132621a68cSalm des_n = 0;
2142621a68cSalm }
2159380925bSalm return (des_ct >= 0 && cbc_encode(des_buf, des_n, fp) >= 0) ? 0 : EOF;
2168b7ade1aSthorpej #else
2178b7ade1aSthorpej return EOF;
2182621a68cSalm #endif
2192621a68cSalm }
2202621a68cSalm
2212621a68cSalm #ifdef DES
2229b082a69Scgd /*
2239b082a69Scgd * get keyword from tty or stdin
2249b082a69Scgd */
2259380925bSalm int
get_keyword(void)226d33a7206Sxtraeme get_keyword(void)
2279b082a69Scgd {
2283811362cStls char *p; /* used to obtain the key */
2299b082a69Scgd Desbuf msgbuf; /* I/O buffer */
2309b082a69Scgd
2319b082a69Scgd /*
2329b082a69Scgd * get the key
2339b082a69Scgd */
2349b082a69Scgd if (*(p = getpass("Enter key: "))) {
2359b082a69Scgd
2369b082a69Scgd /*
2379b082a69Scgd * copy it, nul-padded, into the key area
2389b082a69Scgd */
2399380925bSalm expand_des_key(BUFFER(msgbuf), p);
2409b082a69Scgd MEMZERO(p, _PASSWORD_LEN);
2419380925bSalm set_des_key(msgbuf);
2429b082a69Scgd MEMZERO(msgbuf, sizeof msgbuf);
2439b082a69Scgd return 1;
2449b082a69Scgd }
2459b082a69Scgd return 0;
2469b082a69Scgd }
2479b082a69Scgd
248336e165cScgd
2499b082a69Scgd /*
2509b082a69Scgd * print a warning message and, possibly, terminate
2519b082a69Scgd */
25285d0adbcSdholland static void
des_error(const char * s)2536310b596Schristos des_error(const char *s /* the message */)
2549b082a69Scgd {
255a3542600Sdholland seterrmsg("%s", s ? s : strerror(errno));
2569b082a69Scgd }
2579b082a69Scgd
2589b082a69Scgd /*
2599b082a69Scgd * map a hex character to an integer
2609b082a69Scgd */
26185d0adbcSdholland static int
hex_to_binary(int c,int radix)262d33a7206Sxtraeme hex_to_binary(int c /* char to be converted */,
263d33a7206Sxtraeme int radix /* base (2 to 16) */)
2649b082a69Scgd {
2659b082a69Scgd switch(c) {
2669b082a69Scgd case '0': return(0x0);
2679b082a69Scgd case '1': return(0x1);
2689b082a69Scgd case '2': return(radix > 2 ? 0x2 : -1);
2699b082a69Scgd case '3': return(radix > 3 ? 0x3 : -1);
2709b082a69Scgd case '4': return(radix > 4 ? 0x4 : -1);
2719b082a69Scgd case '5': return(radix > 5 ? 0x5 : -1);
2729b082a69Scgd case '6': return(radix > 6 ? 0x6 : -1);
2739b082a69Scgd case '7': return(radix > 7 ? 0x7 : -1);
2749b082a69Scgd case '8': return(radix > 8 ? 0x8 : -1);
2759b082a69Scgd case '9': return(radix > 9 ? 0x9 : -1);
2769b082a69Scgd case 'A': case 'a': return(radix > 10 ? 0xa : -1);
2779b082a69Scgd case 'B': case 'b': return(radix > 11 ? 0xb : -1);
2789b082a69Scgd case 'C': case 'c': return(radix > 12 ? 0xc : -1);
2799b082a69Scgd case 'D': case 'd': return(radix > 13 ? 0xd : -1);
2809b082a69Scgd case 'E': case 'e': return(radix > 14 ? 0xe : -1);
2819b082a69Scgd case 'F': case 'f': return(radix > 15 ? 0xf : -1);
2829b082a69Scgd }
2839b082a69Scgd /*
2849b082a69Scgd * invalid character
2859b082a69Scgd */
2869b082a69Scgd return(-1);
2879b082a69Scgd }
2889b082a69Scgd
2899b082a69Scgd /*
2909b082a69Scgd * convert the key to a bit pattern
2919b082a69Scgd */
29285d0adbcSdholland static void
expand_des_key(char * obuf,char * inbuf)293d33a7206Sxtraeme expand_des_key(char *obuf /* bit pattern */, char *inbuf /* the key itself */)
2949b082a69Scgd {
2953811362cStls int i, j; /* counter in a for loop */
2969b082a69Scgd int nbuf[64]; /* used for hex/key translation */
2979b082a69Scgd
2989b082a69Scgd /*
2999b082a69Scgd * leading '0x' or '0X' == hex key
3009b082a69Scgd */
301b8a67691Slukem if (inbuf[0] == '0' && (inbuf[1] == 'x' || inbuf[1] == 'X')) {
302b8a67691Slukem inbuf = &inbuf[2];
3039b082a69Scgd /*
3049b082a69Scgd * now translate it, bombing on any illegal hex digit
3059b082a69Scgd */
306ded9763fSchristos for (i = 0; i < 16 && inbuf[i]; i++)
307b8a67691Slukem if ((nbuf[i] = hex_to_binary((int) inbuf[i], 16)) == -1)
3089380925bSalm des_error("bad hex digit in key");
3099b082a69Scgd while (i < 16)
3109b082a69Scgd nbuf[i++] = 0;
3119b082a69Scgd for (i = 0; i < 8; i++)
3129b082a69Scgd obuf[i] =
3139b082a69Scgd ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
3149b082a69Scgd /* preserve parity bits */
3159b082a69Scgd pflag = 1;
3169b082a69Scgd return;
3179b082a69Scgd }
3189b082a69Scgd /*
3199b082a69Scgd * leading '0b' or '0B' == binary key
3209b082a69Scgd */
321b8a67691Slukem if (inbuf[0] == '0' && (inbuf[1] == 'b' || inbuf[1] == 'B')) {
322b8a67691Slukem inbuf = &inbuf[2];
3239b082a69Scgd /*
3249b082a69Scgd * now translate it, bombing on any illegal binary digit
3259b082a69Scgd */
326ded9763fSchristos for (i = 0; i < 16 && inbuf[i]; i++)
327b8a67691Slukem if ((nbuf[i] = hex_to_binary((int) inbuf[i], 2)) == -1)
3289380925bSalm des_error("bad binary digit in key");
3299b082a69Scgd while (i < 64)
3309b082a69Scgd nbuf[i++] = 0;
3319b082a69Scgd for (i = 0; i < 8; i++)
3329b082a69Scgd for (j = 0; j < 8; j++)
3339b082a69Scgd obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
3349b082a69Scgd /* preserve parity bits */
3359b082a69Scgd pflag = 1;
3369b082a69Scgd return;
3379b082a69Scgd }
3389b082a69Scgd /*
3399b082a69Scgd * no special leader -- ASCII
3409b082a69Scgd */
341b8a67691Slukem (void)strncpy(obuf, inbuf, 8);
3429b082a69Scgd }
3439b082a69Scgd
3449b082a69Scgd /*****************
3459b082a69Scgd * DES FUNCTIONS *
3469b082a69Scgd *****************/
3479b082a69Scgd /*
3489b082a69Scgd * This sets the DES key and (if you're using the deszip version)
3499b082a69Scgd * the direction of the transformation. This uses the Sun
3509b082a69Scgd * to map the 64-bit key onto the 56 bits that the key schedule
3519b082a69Scgd * generation routines use: the old way, which just uses the user-
3529b082a69Scgd * supplied 64 bits as is, and the new way, which resets the parity
3539b082a69Scgd * bit to be the same as the low-order bit in each character. The
3549b082a69Scgd * new way generates a greater variety of key schedules, since many
3559b082a69Scgd * systems set the parity (high) bit of each character to 0, and the
3569b082a69Scgd * DES ignores the low order bit of each character.
3579b082a69Scgd */
35885d0adbcSdholland static void
set_des_key(Desbuf buf)359d33a7206Sxtraeme set_des_key(Desbuf buf /* key block */)
3609b082a69Scgd {
3613811362cStls int i, j; /* counter in a for loop */
3623811362cStls int par; /* parity counter */
3639b082a69Scgd
3649b082a69Scgd /*
3659b082a69Scgd * if the parity is not preserved, flip it
3669b082a69Scgd */
3679b082a69Scgd if (!pflag) {
3689b082a69Scgd for (i = 0; i < 8; i++) {
3699b082a69Scgd par = 0;
3709b082a69Scgd for (j = 1; j < 8; j++)
3719b082a69Scgd if ((bits[j]&UCHAR(buf, i)) != 0)
3729b082a69Scgd par++;
3739b082a69Scgd if ((par&01) == 01)
3749b082a69Scgd UCHAR(buf, i) = UCHAR(buf, i)&0177;
3759b082a69Scgd else
3769b082a69Scgd UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
3779b082a69Scgd }
3789b082a69Scgd }
3799b082a69Scgd
3809b082a69Scgd DES_KEY(UBUFFER(buf));
3819b082a69Scgd }
3829b082a69Scgd
3839b082a69Scgd
3849b082a69Scgd /*
3859b082a69Scgd * This encrypts using the Cipher Block Chaining mode of DES
3869b082a69Scgd */
38785d0adbcSdholland static int
cbc_encode(char * msgbuf,int n,FILE * fp)388d33a7206Sxtraeme cbc_encode(char *msgbuf, int n, FILE *fp)
3899b082a69Scgd {
3909b082a69Scgd int inverse = 0; /* 0 to encrypt, 1 to decrypt */
3919b082a69Scgd
3929b082a69Scgd /*
3939b082a69Scgd * do the transformation
3949b082a69Scgd */
3959b082a69Scgd if (n == 8) {
3969b082a69Scgd for (n = 0; n < 8; n++)
3979b082a69Scgd CHAR(msgbuf, n) ^= CHAR(ivec, n);
3989b082a69Scgd DES_XFORM(UBUFFER(msgbuf));
3999b082a69Scgd MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
4009b082a69Scgd return WRITE(BUFFER(msgbuf), 8, fp);
4019b082a69Scgd }
4029b082a69Scgd /*
4039b082a69Scgd * at EOF or last block -- in either case, the last byte contains
4049b082a69Scgd * the character representation of the number of bytes in it
4059b082a69Scgd */
4069b082a69Scgd /*
4079b082a69Scgd MEMZERO(msgbuf + n, 8 - n);
4089b082a69Scgd */
4099b082a69Scgd /*
4109b082a69Scgd * Pad the last block randomly
4119b082a69Scgd */
4129b082a69Scgd (void)MEMCPY(BUFFER(msgbuf + n), BUFFER(pvec), 8 - n);
4139b082a69Scgd CHAR(msgbuf, 7) = n;
4149b082a69Scgd for (n = 0; n < 8; n++)
4159b082a69Scgd CHAR(msgbuf, n) ^= CHAR(ivec, n);
4169b082a69Scgd DES_XFORM(UBUFFER(msgbuf));
4179b082a69Scgd return WRITE(BUFFER(msgbuf), 8, fp);
4189b082a69Scgd }
4199b082a69Scgd
4209b082a69Scgd /*
4219b082a69Scgd * This decrypts using the Cipher Block Chaining mode of DES
4229b082a69Scgd */
42385d0adbcSdholland static int
cbc_decode(char * msgbuf,FILE * fp)424d33a7206Sxtraeme cbc_decode(char *msgbuf /* I/O buffer */,
425d33a7206Sxtraeme FILE *fp /* input file descriptor */)
4269b082a69Scgd {
427b8a67691Slukem Desbuf inbuf; /* temp buffer for initialization vector */
4283811362cStls int n; /* number of bytes actually read */
4293811362cStls int c; /* used to test for EOF */
4309b082a69Scgd int inverse = 1; /* 0 to encrypt, 1 to decrypt */
4319b082a69Scgd
4329b082a69Scgd if ((n = READ(BUFFER(msgbuf), 8, fp)) == 8) {
4339b082a69Scgd /*
4349b082a69Scgd * do the transformation
4359b082a69Scgd */
436b8a67691Slukem MEMCPY(BUFFER(inbuf), BUFFER(msgbuf), 8);
4379b082a69Scgd DES_XFORM(UBUFFER(msgbuf));
4389b082a69Scgd for (c = 0; c < 8; c++)
4399b082a69Scgd UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
440b8a67691Slukem MEMCPY(BUFFER(ivec), BUFFER(inbuf), 8);
4419b082a69Scgd /*
4429b082a69Scgd * if the last one, handle it specially
4439b082a69Scgd */
4449b082a69Scgd if ((c = fgetc(fp)) == EOF) {
4459b082a69Scgd n = CHAR(msgbuf, 7);
4469b082a69Scgd if (n < 0 || n > 7) {
4479380925bSalm des_error("decryption failed (block corrupted)");
4489b082a69Scgd return EOF;
4499b082a69Scgd }
4509b082a69Scgd } else
4519b082a69Scgd (void)ungetc(c, fp);
4529b082a69Scgd return n;
4539b082a69Scgd }
4549b082a69Scgd if (n > 0)
4559380925bSalm des_error("decryption failed (incomplete block)");
456336e165cScgd else if (n < 0)
4579380925bSalm des_error("cannot read file");
4589b082a69Scgd return EOF;
4599b082a69Scgd }
4609b082a69Scgd #endif /* DES */
461