xref: /netbsd-src/bin/ed/cbc.c (revision f8570f8a97f412a33574ec77d412b16dbe332965)
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