xref: /netbsd-src/usr.bin/bdes/bdes.c (revision 0aa2b64219e8591017bb3d659c51545050a6c3ff)
1*0aa2b642Sandvar /*	$NetBSD: bdes.c,v 1.11 2023/06/27 19:30:27 andvar Exp $	*/
2468b4841Sthorpej 
3468b4841Sthorpej /*-
4468b4841Sthorpej  * Copyright (c) 1991, 1993
5468b4841Sthorpej  *	The Regents of the University of California.  All rights reserved.
6468b4841Sthorpej  *
7468b4841Sthorpej  * This code is derived from software contributed to Berkeley by
8468b4841Sthorpej  * Matt Bishop of Dartmouth College.
9468b4841Sthorpej  *
10468b4841Sthorpej  * The United States Government has rights in this work pursuant
11468b4841Sthorpej  * to contract no. NAG 2-680 between the National Aeronautics and
12468b4841Sthorpej  * Space Administration and Dartmouth College.
13468b4841Sthorpej  *
14468b4841Sthorpej  * Redistribution and use in source and binary forms, with or without
15468b4841Sthorpej  * modification, are permitted provided that the following conditions
16468b4841Sthorpej  * are met:
17468b4841Sthorpej  * 1. Redistributions of source code must retain the above copyright
18468b4841Sthorpej  *    notice, this list of conditions and the following disclaimer.
19468b4841Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
20468b4841Sthorpej  *    notice, this list of conditions and the following disclaimer in the
21468b4841Sthorpej  *    documentation and/or other materials provided with the distribution.
2289aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
23468b4841Sthorpej  *    may be used to endorse or promote products derived from this software
24468b4841Sthorpej  *    without specific prior written permission.
25468b4841Sthorpej  *
26468b4841Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27468b4841Sthorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28468b4841Sthorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29468b4841Sthorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30468b4841Sthorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31468b4841Sthorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32468b4841Sthorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33468b4841Sthorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34468b4841Sthorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35468b4841Sthorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36468b4841Sthorpej  * SUCH DAMAGE.
37468b4841Sthorpej  */
38468b4841Sthorpej 
3993bf7731Sthorpej #include <sys/cdefs.h>
40468b4841Sthorpej #ifndef lint
4198e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
4298e5374cSlukem  The Regents of the University of California.  All rights reserved.");
43468b4841Sthorpej #endif /* not lint */
44468b4841Sthorpej 
45468b4841Sthorpej #ifndef lint
46468b4841Sthorpej #if 0
47468b4841Sthorpej static char sccsid[] = "@(#)bdes.c	8.1 (Berkeley) 6/6/93";
48468b4841Sthorpej #else
49*0aa2b642Sandvar __RCSID("$NetBSD: bdes.c,v 1.11 2023/06/27 19:30:27 andvar Exp $");
50468b4841Sthorpej #endif
51468b4841Sthorpej #endif /* not lint */
52468b4841Sthorpej 
53468b4841Sthorpej /*
54468b4841Sthorpej  * BDES -- DES encryption package for Berkeley Software Distribution 4.4
55468b4841Sthorpej  * options:
56468b4841Sthorpej  *	-a	key is in ASCII
57468b4841Sthorpej  *	-b	use ECB (electronic code book) mode
58468b4841Sthorpej  *	-d	invert (decrypt) input
59468b4841Sthorpej  *	-f b	use b-bit CFB (cipher feedback) mode
60468b4841Sthorpej  *	-F b	use b-bit CFB (cipher feedback) alternative mode
61468b4841Sthorpej  *	-k key	use key as the cryptographic key
62468b4841Sthorpej  *	-m b	generate a MAC of length b
63468b4841Sthorpej  *	-o b	use b-bit OFB (output feedback) mode
64468b4841Sthorpej  *	-p	don't reset the parity bit
65468b4841Sthorpej  *	-v v	use v as the initialization vector (ignored for ECB)
66468b4841Sthorpej  * note: the last character of the last block is the integer indicating
67468b4841Sthorpej  * how many characters of that block are to be output
68468b4841Sthorpej  *
69468b4841Sthorpej  * Author: Matt Bishop
70468b4841Sthorpej  *	   Department of Mathematics and Computer Science
71468b4841Sthorpej  *	   Dartmouth College
72468b4841Sthorpej  *	   Hanover, NH  03755
73468b4841Sthorpej  * Email:  Matt.Bishop@dartmouth.edu
74468b4841Sthorpej  *	   ...!decvax!dartvax!Matt.Bishop
75468b4841Sthorpej  *
76468b4841Sthorpej  * See Technical Report PCS-TR91-158, Department of Mathematics and Computer
77468b4841Sthorpej  * Science, Dartmouth College, for a detailed description of the implemen-
78468b4841Sthorpej  * tation and differences between it and Sun's.  The DES is described in
79468b4841Sthorpej  * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page
80468b4841Sthorpej  * or the technical report for a complete reference).
81468b4841Sthorpej  */
82468b4841Sthorpej 
83468b4841Sthorpej #include <errno.h>
84468b4841Sthorpej #include <unistd.h>
85468b4841Sthorpej #include <stdio.h>
86468b4841Sthorpej #include <ctype.h>
87468b4841Sthorpej #include <stdlib.h>
88468b4841Sthorpej #include <string.h>
89468b4841Sthorpej 
90468b4841Sthorpej /*
91468b4841Sthorpej  * BSD and System V systems offer special library calls that do
92468b4841Sthorpej  * block moves and fills, so if possible we take advantage of them
93468b4841Sthorpej  */
94468b4841Sthorpej #define	MEMCPY(dest,src,len)	bcopy((src),(dest),(len))
95468b4841Sthorpej #define	MEMZERO(dest,len)	bzero((dest),(len))
96468b4841Sthorpej 
97468b4841Sthorpej /* Hide the calls to the primitive encryption routines. */
98468b4841Sthorpej #define	FASTWAY
99468b4841Sthorpej #ifdef	FASTWAY
100468b4841Sthorpej #define	DES_KEY(buf) \
101468b4841Sthorpej 	if (des_setkey(buf)) \
10293bf7731Sthorpej 		bdes_err(0, "des_setkey");
103468b4841Sthorpej #define	DES_XFORM(buf) \
104468b4841Sthorpej 	if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
10593bf7731Sthorpej 		bdes_err(0, "des_cipher");
106468b4841Sthorpej #else
107468b4841Sthorpej #define	DES_KEY(buf)	{						\
108468b4841Sthorpej 				char bits1[64];	/* bits of key */	\
109468b4841Sthorpej 				expand(buf, bits1);			\
110468b4841Sthorpej 				if (setkey(bits1))			\
11193bf7731Sthorpej 					bdes_err(0, "setkey");		\
112468b4841Sthorpej 			}
113468b4841Sthorpej #define	DES_XFORM(buf)	{						\
114468b4841Sthorpej 				char bits1[64];	/* bits of message */	\
115468b4841Sthorpej 				expand(buf, bits1);			\
116468b4841Sthorpej 				if (encrypt(bits1, inverse))		\
11793bf7731Sthorpej 					bdes_err(0, "encrypt");		\
118468b4841Sthorpej 				compress(bits1, buf);			\
119468b4841Sthorpej 			}
120468b4841Sthorpej #endif
121468b4841Sthorpej 
122468b4841Sthorpej /*
123468b4841Sthorpej  * this does an error-checking write
124468b4841Sthorpej  */
125468b4841Sthorpej #define	READ(buf, n)	fread(buf, sizeof(char), n, stdin)
126468b4841Sthorpej #define WRITE(buf,n)						\
127238e973fSlukem 		if (fwrite(buf, sizeof(char), n, stdout) != (size_t)n)	\
12893bf7731Sthorpej 			bdes_err(bn, NULL);
129468b4841Sthorpej 
130468b4841Sthorpej /*
131468b4841Sthorpej  * some things to make references easier
132468b4841Sthorpej  */
133468b4841Sthorpej typedef char Desbuf[8];
134468b4841Sthorpej #define	CHAR(x,i)	(x[i])
135468b4841Sthorpej #define	UCHAR(x,i)	(x[i])
136468b4841Sthorpej #define	BUFFER(x)	(x)
137468b4841Sthorpej #define	UBUFFER(x)	(x)
138468b4841Sthorpej 
139468b4841Sthorpej /*
140468b4841Sthorpej  * global variables and related macros
141468b4841Sthorpej  */
142468b4841Sthorpej #define KEY_DEFAULT		0	/* interpret radix of key from key */
143468b4841Sthorpej #define KEY_ASCII		1	/* key is in ASCII characters */
144d9a44d71Sjoerg static int keybase = KEY_DEFAULT;	/* how to interpret the key */
145468b4841Sthorpej 
146d9a44d71Sjoerg static enum { 				/* encrypt, decrypt, authenticate */
147468b4841Sthorpej 	MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
148468b4841Sthorpej } mode = MODE_ENCRYPT;
149d9a44d71Sjoerg static enum {				/* ecb, cbc, cfb, cfba, ofb? */
150468b4841Sthorpej 	ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
151468b4841Sthorpej } alg = ALG_CBC;
152468b4841Sthorpej 
153d9a44d71Sjoerg static Desbuf ivec;				/* initialization vector */
154d9a44d71Sjoerg static const char bits[] = {				/* used to extract bits from a char */
155468b4841Sthorpej 	'\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
156468b4841Sthorpej };
157d9a44d71Sjoerg static int inverse;				/* 0 to encrypt, 1 to decrypt */
158d9a44d71Sjoerg static int macbits = -1;			/* number of bits in authentication */
159d9a44d71Sjoerg static int fbbits = -1;			/* number of feedback bits */
160d9a44d71Sjoerg static int pflag;				/* 1 to preserve parity bits */
161468b4841Sthorpej 
162d9a44d71Sjoerg static int	setbits(char *, int);
163d9a44d71Sjoerg static void	bdes_err(int, const char *) __dead;
164d9a44d71Sjoerg static int	tobinhex(char, int);
165d9a44d71Sjoerg static void	cvtkey(char *, char *);
166d9a44d71Sjoerg static void	makekey(Desbuf);
167d9a44d71Sjoerg static void	ecbenc(void);
168d9a44d71Sjoerg static void	ecbdec(void);
169d9a44d71Sjoerg static void	cbcenc(void);
170d9a44d71Sjoerg static void	cbcdec(void);
171d9a44d71Sjoerg static void	cbcauth(void);
172d9a44d71Sjoerg static void	cfbenc(void);
173d9a44d71Sjoerg static void	cfbdec(void);
174d9a44d71Sjoerg static void	cfbaenc(void);
175d9a44d71Sjoerg static void	cfbadec(void);
176d9a44d71Sjoerg static void	ofbenc(void);
177d9a44d71Sjoerg static void	ofbdec(void);
178d9a44d71Sjoerg static void	cfbauth(void);
179d9a44d71Sjoerg #ifndef FASTWAY
180d9a44d71Sjoerg static void	expand(Desbuf, char *);
181d9a44d71Sjoerg static void	compress(char *, Desbuf);
182d9a44d71Sjoerg #endif
183d9a44d71Sjoerg static void	usage(void) __dead;
18493bf7731Sthorpej 
18593bf7731Sthorpej int
main(int ac,char * av[])18693bf7731Sthorpej main(int ac, char *av[])
187468b4841Sthorpej {
188468b4841Sthorpej 	register int i;			/* counter in a for loop */
189468b4841Sthorpej 	register char *p;		/* used to obtain the key */
190468b4841Sthorpej 	Desbuf msgbuf;			/* I/O buffer */
191*0aa2b642Sandvar 	int kflag;			/* command-line encryption key */
192468b4841Sthorpej 	int argc;			/* the real arg count */
193468b4841Sthorpej 	char **argv;			/* the real argument vector */
194468b4841Sthorpej 
195468b4841Sthorpej 	/*
196468b4841Sthorpej 	 * Hide the arguments from ps(1) by making private copies of them
197468b4841Sthorpej 	 * and clobbering the global (visible to ps(1)) ones.
198468b4841Sthorpej 	 */
199468b4841Sthorpej 	argc = ac;
200468b4841Sthorpej 	ac = 1;
201468b4841Sthorpej 	argv = malloc((argc + 1) * sizeof(char *));
202468b4841Sthorpej 	for (i = 0; i < argc; ++i) {
203468b4841Sthorpej 		argv[i] = strdup(av[i]);
204468b4841Sthorpej 		MEMZERO(av[i], strlen(av[i]));
205468b4841Sthorpej 	}
206468b4841Sthorpej 	argv[argc] = NULL;
207468b4841Sthorpej 
208468b4841Sthorpej 	/* initialize the initialization vctor */
209468b4841Sthorpej 	MEMZERO(ivec, 8);
210468b4841Sthorpej 
211468b4841Sthorpej 	/* process the argument list */
212468b4841Sthorpej 	kflag = 0;
213b46ec3b2Smjl 	while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1)
214468b4841Sthorpej 		switch(i) {
215468b4841Sthorpej 		case 'a':		/* key is ASCII */
216468b4841Sthorpej 			keybase = KEY_ASCII;
217468b4841Sthorpej 			break;
218468b4841Sthorpej 		case 'b':		/* use ECB mode */
219468b4841Sthorpej 			alg = ALG_ECB;
220468b4841Sthorpej 			break;
221468b4841Sthorpej 		case 'd':		/* decrypt */
222468b4841Sthorpej 			mode = MODE_DECRYPT;
223468b4841Sthorpej 			break;
224468b4841Sthorpej 		case 'F':		/* use alternative CFB mode */
225468b4841Sthorpej 			alg = ALG_CFBA;
226468b4841Sthorpej 			if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0)
22793bf7731Sthorpej 				bdes_err(-1,
22893bf7731Sthorpej 				    "-F: number must be 1-56 inclusive");
229468b4841Sthorpej 			else if (fbbits == -1)
23093bf7731Sthorpej 				bdes_err(-1,
23193bf7731Sthorpej 				    "-F: number must be a multiple of 7");
232468b4841Sthorpej 			break;
233468b4841Sthorpej 		case 'f':		/* use CFB mode */
234468b4841Sthorpej 			alg = ALG_CFB;
235468b4841Sthorpej 			if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
23693bf7731Sthorpej 				bdes_err(-1,
23793bf7731Sthorpej 				    "-f: number must be 1-64 inclusive");
238468b4841Sthorpej 			else if (fbbits == -1)
23993bf7731Sthorpej 				bdes_err(-1,
24093bf7731Sthorpej 				    "-f: number must be a multiple of 8");
241468b4841Sthorpej 			break;
242468b4841Sthorpej 		case 'k':		/* encryption key */
243468b4841Sthorpej 			kflag = 1;
244468b4841Sthorpej 			cvtkey(BUFFER(msgbuf), optarg);
245468b4841Sthorpej 			break;
246468b4841Sthorpej 		case 'm':		/* number of bits for MACing */
247468b4841Sthorpej 			mode = MODE_AUTHENTICATE;
248468b4841Sthorpej 			if ((macbits = setbits(optarg, 1)) > 64)
24993bf7731Sthorpej 				bdes_err(-1,
25093bf7731Sthorpej 				    "-m: number must be 0-64 inclusive");
251468b4841Sthorpej 			break;
252468b4841Sthorpej 		case 'o':		/* use OFB mode */
253468b4841Sthorpej 			alg = ALG_OFB;
254468b4841Sthorpej 			if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
25593bf7731Sthorpej 				bdes_err(-1,
25693bf7731Sthorpej 				    "-o: number must be 1-64 inclusive");
257468b4841Sthorpej 			else if (fbbits == -1)
25893bf7731Sthorpej 				bdes_err(-1,
25993bf7731Sthorpej 				    "-o: number must be a multiple of 8");
260468b4841Sthorpej 			break;
261468b4841Sthorpej 		case 'p':		/* preserve parity bits */
262468b4841Sthorpej 			pflag = 1;
263468b4841Sthorpej 			break;
264468b4841Sthorpej 		case 'v':		/* set initialization vector */
265468b4841Sthorpej 			cvtkey(BUFFER(ivec), optarg);
266468b4841Sthorpej 			break;
267468b4841Sthorpej 		default:		/* error */
268468b4841Sthorpej 			usage();
269468b4841Sthorpej 		}
270468b4841Sthorpej 
271468b4841Sthorpej 	if (!kflag) {
272468b4841Sthorpej 		/*
273468b4841Sthorpej 		 * if the key's not ASCII, assume it is
274468b4841Sthorpej 		 */
275468b4841Sthorpej 		keybase = KEY_ASCII;
276468b4841Sthorpej 		/*
277468b4841Sthorpej 		 * get the key
278468b4841Sthorpej 		 */
279468b4841Sthorpej 		p = getpass("Enter key: ");
280468b4841Sthorpej 		/*
281468b4841Sthorpej 		 * copy it, nul-padded, into the key area
282468b4841Sthorpej 		 */
283468b4841Sthorpej 		cvtkey(BUFFER(msgbuf), p);
284468b4841Sthorpej 	}
285468b4841Sthorpej 
286468b4841Sthorpej 	makekey(msgbuf);
287468b4841Sthorpej 	inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT;
288468b4841Sthorpej 
289468b4841Sthorpej 	switch(alg) {
290468b4841Sthorpej 	case ALG_CBC:
291468b4841Sthorpej 		switch(mode) {
292468b4841Sthorpej 		case MODE_AUTHENTICATE:	/* authenticate using CBC mode */
293468b4841Sthorpej 			cbcauth();
294468b4841Sthorpej 			break;
295468b4841Sthorpej 		case MODE_DECRYPT:	/* decrypt using CBC mode */
296468b4841Sthorpej 			cbcdec();
297468b4841Sthorpej 			break;
298468b4841Sthorpej 		case MODE_ENCRYPT:	/* encrypt using CBC mode */
299468b4841Sthorpej 			cbcenc();
300468b4841Sthorpej 			break;
301468b4841Sthorpej 		}
302468b4841Sthorpej 		break;
303468b4841Sthorpej 	case ALG_CFB:
304468b4841Sthorpej 		switch(mode) {
305468b4841Sthorpej 		case MODE_AUTHENTICATE:	/* authenticate using CFB mode */
306468b4841Sthorpej 			cfbauth();
307468b4841Sthorpej 			break;
308468b4841Sthorpej 		case MODE_DECRYPT:	/* decrypt using CFB mode */
309468b4841Sthorpej 			cfbdec();
310468b4841Sthorpej 			break;
311468b4841Sthorpej 		case MODE_ENCRYPT:	/* encrypt using CFB mode */
312468b4841Sthorpej 			cfbenc();
313468b4841Sthorpej 			break;
314468b4841Sthorpej 		}
315468b4841Sthorpej 		break;
316468b4841Sthorpej 	case ALG_CFBA:
317468b4841Sthorpej 		switch(mode) {
318468b4841Sthorpej 		case MODE_AUTHENTICATE:	/* authenticate using CFBA mode */
31993bf7731Sthorpej 			bdes_err(-1, "can't authenticate with CFBA mode");
320468b4841Sthorpej 			break;
321468b4841Sthorpej 		case MODE_DECRYPT:	/* decrypt using CFBA mode */
322468b4841Sthorpej 			cfbadec();
323468b4841Sthorpej 			break;
324468b4841Sthorpej 		case MODE_ENCRYPT:	/* encrypt using CFBA mode */
325468b4841Sthorpej 			cfbaenc();
326468b4841Sthorpej 			break;
327468b4841Sthorpej 		}
328468b4841Sthorpej 		break;
329468b4841Sthorpej 	case ALG_ECB:
330468b4841Sthorpej 		switch(mode) {
331468b4841Sthorpej 		case MODE_AUTHENTICATE:	/* authenticate using ECB mode */
33293bf7731Sthorpej 			bdes_err(-1, "can't authenticate with ECB mode");
333468b4841Sthorpej 			break;
334468b4841Sthorpej 		case MODE_DECRYPT:	/* decrypt using ECB mode */
335468b4841Sthorpej 			ecbdec();
336468b4841Sthorpej 			break;
337468b4841Sthorpej 		case MODE_ENCRYPT:	/* encrypt using ECB mode */
338468b4841Sthorpej 			ecbenc();
339468b4841Sthorpej 			break;
340468b4841Sthorpej 		}
341468b4841Sthorpej 		break;
342468b4841Sthorpej 	case ALG_OFB:
343468b4841Sthorpej 		switch(mode) {
344468b4841Sthorpej 		case MODE_AUTHENTICATE:	/* authenticate using OFB mode */
34593bf7731Sthorpej 			bdes_err(-1, "can't authenticate with OFB mode");
346468b4841Sthorpej 			break;
347468b4841Sthorpej 		case MODE_DECRYPT:	/* decrypt using OFB mode */
348468b4841Sthorpej 			ofbdec();
349468b4841Sthorpej 			break;
350468b4841Sthorpej 		case MODE_ENCRYPT:	/* encrypt using OFB mode */
351468b4841Sthorpej 			ofbenc();
352468b4841Sthorpej 			break;
353468b4841Sthorpej 		}
354468b4841Sthorpej 		break;
355468b4841Sthorpej 	}
356468b4841Sthorpej 	exit(0);
357468b4841Sthorpej }
358468b4841Sthorpej 
359468b4841Sthorpej /*
360468b4841Sthorpej  * print a warning message and, possibly, terminate
361468b4841Sthorpej  */
362d9a44d71Sjoerg static void
bdes_err(int n,const char * s)36393bf7731Sthorpej bdes_err(int n, const char *s)
364468b4841Sthorpej {
365468b4841Sthorpej 	if (n > 0)
366468b4841Sthorpej 		(void)fprintf(stderr, "bdes (block %d): ", n);
367468b4841Sthorpej 	else
368468b4841Sthorpej 		(void)fprintf(stderr, "bdes: ");
369468b4841Sthorpej 	(void)fprintf(stderr, "%s\n", s ? s : strerror(errno));
370468b4841Sthorpej 	exit(1);
371468b4841Sthorpej }
372468b4841Sthorpej 
373468b4841Sthorpej /*
374468b4841Sthorpej  * map a hex character to an integer
375468b4841Sthorpej  */
376d9a44d71Sjoerg static int
tobinhex(char c,int radix)37793bf7731Sthorpej tobinhex(char c, int radix)
378468b4841Sthorpej {
379468b4841Sthorpej 	switch(c) {
380468b4841Sthorpej 	case '0':		return(0x0);
381468b4841Sthorpej 	case '1':		return(0x1);
382468b4841Sthorpej 	case '2':		return(radix > 2 ? 0x2 : -1);
383468b4841Sthorpej 	case '3':		return(radix > 3 ? 0x3 : -1);
384468b4841Sthorpej 	case '4':		return(radix > 4 ? 0x4 : -1);
385468b4841Sthorpej 	case '5':		return(radix > 5 ? 0x5 : -1);
386468b4841Sthorpej 	case '6':		return(radix > 6 ? 0x6 : -1);
387468b4841Sthorpej 	case '7':		return(radix > 7 ? 0x7 : -1);
388468b4841Sthorpej 	case '8':		return(radix > 8 ? 0x8 : -1);
389468b4841Sthorpej 	case '9':		return(radix > 9 ? 0x9 : -1);
390468b4841Sthorpej 	case 'A': case 'a':	return(radix > 10 ? 0xa : -1);
391468b4841Sthorpej 	case 'B': case 'b':	return(radix > 11 ? 0xb : -1);
392468b4841Sthorpej 	case 'C': case 'c':	return(radix > 12 ? 0xc : -1);
393468b4841Sthorpej 	case 'D': case 'd':	return(radix > 13 ? 0xd : -1);
394468b4841Sthorpej 	case 'E': case 'e':	return(radix > 14 ? 0xe : -1);
395468b4841Sthorpej 	case 'F': case 'f':	return(radix > 15 ? 0xf : -1);
396468b4841Sthorpej 	}
397468b4841Sthorpej 	/*
398468b4841Sthorpej 	 * invalid character
399468b4841Sthorpej 	 */
400468b4841Sthorpej 	return(-1);
401468b4841Sthorpej }
402468b4841Sthorpej 
403468b4841Sthorpej /*
404468b4841Sthorpej  * convert the key to a bit pattern
405468b4841Sthorpej  */
406d9a44d71Sjoerg static void
cvtkey(char * obuf,char * ibuf)40793bf7731Sthorpej cvtkey(char *obuf, char *ibuf)
408468b4841Sthorpej {
409468b4841Sthorpej 	register int i, j;		/* counter in a for loop */
410468b4841Sthorpej 	int nbuf[64];			/* used for hex/key translation */
411468b4841Sthorpej 
412468b4841Sthorpej 	/*
413468b4841Sthorpej 	 * just switch on the key base
414468b4841Sthorpej 	 */
415468b4841Sthorpej 	switch(keybase) {
416468b4841Sthorpej 	case KEY_ASCII:			/* ascii to integer */
417468b4841Sthorpej 		(void)strncpy(obuf, ibuf, 8);
418468b4841Sthorpej 		return;
419468b4841Sthorpej 	case KEY_DEFAULT:		/* tell from context */
420468b4841Sthorpej 		/*
421468b4841Sthorpej 		 * leading '0x' or '0X' == hex key
422468b4841Sthorpej 		 */
423468b4841Sthorpej 		if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) {
424468b4841Sthorpej 			ibuf = &ibuf[2];
425468b4841Sthorpej 			/*
426468b4841Sthorpej 			 * now translate it, bombing on any illegal hex digit
427468b4841Sthorpej 			 */
42851d0c372Schristos 			for (i = 0; i < 16 && ibuf[i]; i++)
429468b4841Sthorpej 				if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1)
43093bf7731Sthorpej 					bdes_err(-1, "bad hex digit in key");
431468b4841Sthorpej 			while (i < 16)
432468b4841Sthorpej 				nbuf[i++] = 0;
433468b4841Sthorpej 			for (i = 0; i < 8; i++)
434468b4841Sthorpej 				obuf[i] =
435468b4841Sthorpej 				    ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
436468b4841Sthorpej 			/* preserve parity bits */
437468b4841Sthorpej 			pflag = 1;
438468b4841Sthorpej 			return;
439468b4841Sthorpej 		}
440468b4841Sthorpej 		/*
441468b4841Sthorpej 		 * leading '0b' or '0B' == binary key
442468b4841Sthorpej 		 */
443468b4841Sthorpej 		if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) {
444468b4841Sthorpej 			ibuf = &ibuf[2];
445468b4841Sthorpej 			/*
446468b4841Sthorpej 			 * now translate it, bombing on any illegal binary digit
447468b4841Sthorpej 			 */
448468b4841Sthorpej 			for (i = 0; ibuf[i] && i < 16; i++)
449468b4841Sthorpej 				if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1)
45093bf7731Sthorpej 					bdes_err(-1, "bad binary digit in key");
451468b4841Sthorpej 			while (i < 64)
452468b4841Sthorpej 				nbuf[i++] = 0;
453468b4841Sthorpej 			for (i = 0; i < 8; i++)
454468b4841Sthorpej 				for (j = 0; j < 8; j++)
455468b4841Sthorpej 					obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
456468b4841Sthorpej 			/* preserve parity bits */
457468b4841Sthorpej 			pflag = 1;
458468b4841Sthorpej 			return;
459468b4841Sthorpej 		}
460468b4841Sthorpej 		/*
461468b4841Sthorpej 		 * no special leader -- ASCII
462468b4841Sthorpej 		 */
463468b4841Sthorpej 		(void)strncpy(obuf, ibuf, 8);
464468b4841Sthorpej 	}
465468b4841Sthorpej }
466468b4841Sthorpej 
467468b4841Sthorpej /*
468468b4841Sthorpej  * convert an ASCII string into a decimal number:
469f77de37cSdsl  * 1. must be between 0 and 64 inclusive (or 56, checked by caller)
470468b4841Sthorpej  * 2. must be a valid decimal number
471468b4841Sthorpej  * 3. must be a multiple of mult
472468b4841Sthorpej  */
473d9a44d71Sjoerg static int
setbits(char * s,int mult)47493bf7731Sthorpej setbits(char *s, int mult)
475468b4841Sthorpej {
476f77de37cSdsl 	char *p;
477f77de37cSdsl 	int n;		/* the integer collected */
478468b4841Sthorpej 
479f77de37cSdsl 	n = strtoul(s, &p, 10);
480f77de37cSdsl 	if (*p != 0)
48193bf7731Sthorpej 		bdes_err(-1, "bad decimal digit in MAC length");
482468b4841Sthorpej 	/*
483468b4841Sthorpej 	 * be sure it's a multiple of mult
484468b4841Sthorpej 	 */
485468b4841Sthorpej 	return((n % mult != 0) ? -1 : n);
486468b4841Sthorpej }
487468b4841Sthorpej 
488468b4841Sthorpej /*****************
489468b4841Sthorpej  * DES FUNCTIONS *
490468b4841Sthorpej  *****************/
491468b4841Sthorpej /*
492468b4841Sthorpej  * This sets the DES key and (if you're using the deszip version)
493468b4841Sthorpej  * the direction of the transformation.  This uses the Sun
494468b4841Sthorpej  * to map the 64-bit key onto the 56 bits that the key schedule
495468b4841Sthorpej  * generation routines use: the old way, which just uses the user-
496468b4841Sthorpej  * supplied 64 bits as is, and the new way, which resets the parity
497468b4841Sthorpej  * bit to be the same as the low-order bit in each character.  The
498468b4841Sthorpej  * new way generates a greater variety of key schedules, since many
499468b4841Sthorpej  * systems set the parity (high) bit of each character to 0, and the
500468b4841Sthorpej  * DES ignores the low order bit of each character.
501468b4841Sthorpej  */
502d9a44d71Sjoerg static void
makekey(Desbuf buf)50393bf7731Sthorpej makekey(Desbuf buf)
504468b4841Sthorpej {
505468b4841Sthorpej 	register int i, j;			/* counter in a for loop */
506468b4841Sthorpej 	register int par;			/* parity counter */
507468b4841Sthorpej 
508468b4841Sthorpej 	/*
509468b4841Sthorpej 	 * if the parity is not preserved, flip it
510468b4841Sthorpej 	 */
511468b4841Sthorpej 	if (!pflag) {
512468b4841Sthorpej 		for (i = 0; i < 8; i++) {
513468b4841Sthorpej 			par = 0;
514468b4841Sthorpej 			for (j = 1; j < 8; j++)
515468b4841Sthorpej 				if ((bits[j]&UCHAR(buf, i)) != 0)
516468b4841Sthorpej 					par++;
517468b4841Sthorpej 			if ((par&01) == 01)
518468b4841Sthorpej 				UCHAR(buf, i) = UCHAR(buf, i)&0177;
519468b4841Sthorpej 			else
520468b4841Sthorpej 				UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
521468b4841Sthorpej 		}
522468b4841Sthorpej 	}
523468b4841Sthorpej 
524468b4841Sthorpej 	DES_KEY(UBUFFER(buf));
525468b4841Sthorpej }
526468b4841Sthorpej 
527468b4841Sthorpej /*
528468b4841Sthorpej  * This encrypts using the Electronic Code Book mode of DES
529468b4841Sthorpej  */
530d9a44d71Sjoerg static void
ecbenc(void)53193bf7731Sthorpej ecbenc(void)
532468b4841Sthorpej {
533468b4841Sthorpej 	register int n;		/* number of bytes actually read */
534468b4841Sthorpej 	register int bn;	/* block number */
535468b4841Sthorpej 	Desbuf msgbuf;		/* I/O buffer */
536468b4841Sthorpej 
537468b4841Sthorpej 	for (bn = 0; (n = READ(BUFFER(msgbuf),  8)) == 8; bn++) {
538468b4841Sthorpej 		/*
539468b4841Sthorpej 		 * do the transformation
540468b4841Sthorpej 		 */
541468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
542468b4841Sthorpej 		WRITE(BUFFER(msgbuf), 8);
543468b4841Sthorpej 	}
544468b4841Sthorpej 	/*
545468b4841Sthorpej 	 * at EOF or last block -- in either ase, the last byte contains
546468b4841Sthorpej 	 * the character representation of the number of bytes in it
547468b4841Sthorpej 	 */
548468b4841Sthorpej 	bn++;
549468b4841Sthorpej 	MEMZERO(&CHAR(msgbuf, n), 8 - n);
550468b4841Sthorpej 	CHAR(msgbuf, 7) = n;
551468b4841Sthorpej 	DES_XFORM(UBUFFER(msgbuf));
552468b4841Sthorpej 	WRITE(BUFFER(msgbuf), 8);
553468b4841Sthorpej 
554468b4841Sthorpej }
555468b4841Sthorpej 
556468b4841Sthorpej /*
557468b4841Sthorpej  * This decrypts using the Electronic Code Book mode of DES
558468b4841Sthorpej  */
559d9a44d71Sjoerg static void
ecbdec(void)56093bf7731Sthorpej ecbdec(void)
561468b4841Sthorpej {
562468b4841Sthorpej 	register int n;		/* number of bytes actually read */
563468b4841Sthorpej 	register int c;		/* used to test for EOF */
564468b4841Sthorpej 	register int bn;	/* block number */
565468b4841Sthorpej 	Desbuf msgbuf;		/* I/O buffer */
566468b4841Sthorpej 
567468b4841Sthorpej 	for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
568468b4841Sthorpej 		/*
569468b4841Sthorpej 		 * do the transformation
570468b4841Sthorpej 		 */
571468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
572468b4841Sthorpej 		/*
573468b4841Sthorpej 		 * if the last one, handle it specially
574468b4841Sthorpej 		 */
575468b4841Sthorpej 		if ((c = getchar()) == EOF) {
576468b4841Sthorpej 			n = CHAR(msgbuf, 7);
577468b4841Sthorpej 			if (n < 0 || n > 7)
57893bf7731Sthorpej 				bdes_err(bn,
57993bf7731Sthorpej 				    "decryption failed (block corrupted)");
580468b4841Sthorpej 		}
581468b4841Sthorpej 		else
582468b4841Sthorpej 			(void)ungetc(c, stdin);
583468b4841Sthorpej 		WRITE(BUFFER(msgbuf), n);
584468b4841Sthorpej 	}
585468b4841Sthorpej 	if (n > 0)
58693bf7731Sthorpej 		bdes_err(bn, "decryption failed (incomplete block)");
587468b4841Sthorpej }
588468b4841Sthorpej 
589468b4841Sthorpej /*
590468b4841Sthorpej  * This encrypts using the Cipher Block Chaining mode of DES
591468b4841Sthorpej  */
592d9a44d71Sjoerg static void
cbcenc(void)59393bf7731Sthorpej cbcenc(void)
594468b4841Sthorpej {
595468b4841Sthorpej 	register int n;		/* number of bytes actually read */
596468b4841Sthorpej 	register int bn;	/* block number */
597468b4841Sthorpej 	Desbuf msgbuf;		/* I/O buffer */
598468b4841Sthorpej 
599468b4841Sthorpej 	/*
600468b4841Sthorpej 	 * do the transformation
601468b4841Sthorpej 	 */
602468b4841Sthorpej 	for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
603468b4841Sthorpej 		for (n = 0; n < 8; n++)
604468b4841Sthorpej 			CHAR(msgbuf, n) ^= CHAR(ivec, n);
605468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
606468b4841Sthorpej 		MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
607468b4841Sthorpej 		WRITE(BUFFER(msgbuf), 8);
608468b4841Sthorpej 	}
609468b4841Sthorpej 	/*
610468b4841Sthorpej 	 * at EOF or last block -- in either case, the last byte contains
611468b4841Sthorpej 	 * the character representation of the number of bytes in it
612468b4841Sthorpej 	 */
613468b4841Sthorpej 	bn++;
614468b4841Sthorpej 	MEMZERO(&CHAR(msgbuf, n), 8 - n);
615468b4841Sthorpej 	CHAR(msgbuf, 7) = n;
616468b4841Sthorpej 	for (n = 0; n < 8; n++)
617468b4841Sthorpej 		CHAR(msgbuf, n) ^= CHAR(ivec, n);
618468b4841Sthorpej 	DES_XFORM(UBUFFER(msgbuf));
619468b4841Sthorpej 	WRITE(BUFFER(msgbuf), 8);
620468b4841Sthorpej 
621468b4841Sthorpej }
622468b4841Sthorpej 
623468b4841Sthorpej /*
624468b4841Sthorpej  * This decrypts using the Cipher Block Chaining mode of DES
625468b4841Sthorpej  */
626d9a44d71Sjoerg static void
cbcdec(void)62793bf7731Sthorpej cbcdec(void)
628468b4841Sthorpej {
629468b4841Sthorpej 	register int n;		/* number of bytes actually read */
630468b4841Sthorpej 	Desbuf msgbuf;		/* I/O buffer */
631468b4841Sthorpej 	Desbuf ibuf;		/* temp buffer for initialization vector */
632468b4841Sthorpej 	register int c;		/* used to test for EOF */
633468b4841Sthorpej 	register int bn;	/* block number */
634468b4841Sthorpej 
635468b4841Sthorpej 	for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
636468b4841Sthorpej 		/*
637468b4841Sthorpej 		 * do the transformation
638468b4841Sthorpej 		 */
639468b4841Sthorpej 		MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8);
640468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
641468b4841Sthorpej 		for (c = 0; c < 8; c++)
642468b4841Sthorpej 			UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
643468b4841Sthorpej 		MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8);
644468b4841Sthorpej 		/*
645468b4841Sthorpej 		 * if the last one, handle it specially
646468b4841Sthorpej 		 */
647468b4841Sthorpej 		if ((c = getchar()) == EOF) {
648468b4841Sthorpej 			n = CHAR(msgbuf, 7);
649468b4841Sthorpej 			if (n < 0 || n > 7)
65093bf7731Sthorpej 				bdes_err(bn,
65193bf7731Sthorpej 				    "decryption failed (block corrupted)");
652468b4841Sthorpej 		}
653468b4841Sthorpej 		else
654468b4841Sthorpej 			(void)ungetc(c, stdin);
655468b4841Sthorpej 		WRITE(BUFFER(msgbuf), n);
656468b4841Sthorpej 	}
657468b4841Sthorpej 	if (n > 0)
65893bf7731Sthorpej 		bdes_err(bn, "decryption failed (incomplete block)");
659468b4841Sthorpej }
660468b4841Sthorpej 
661468b4841Sthorpej /*
662468b4841Sthorpej  * This authenticates using the Cipher Block Chaining mode of DES
663468b4841Sthorpej  */
664d9a44d71Sjoerg static void
cbcauth(void)66593bf7731Sthorpej cbcauth(void)
666468b4841Sthorpej {
667468b4841Sthorpej 	register int n, j;		/* number of bytes actually read */
668468b4841Sthorpej 	Desbuf msgbuf;		/* I/O buffer */
669468b4841Sthorpej 	Desbuf encbuf;		/* encryption buffer */
670468b4841Sthorpej 
671468b4841Sthorpej 	/*
672468b4841Sthorpej 	 * do the transformation
673468b4841Sthorpej 	 * note we DISCARD the encrypted block;
674468b4841Sthorpej 	 * we only care about the last one
675468b4841Sthorpej 	 */
676468b4841Sthorpej 	while ((n = READ(BUFFER(msgbuf), 8)) == 8) {
677468b4841Sthorpej 		for (n = 0; n < 8; n++)
678468b4841Sthorpej 			CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
679468b4841Sthorpej 		DES_XFORM(UBUFFER(encbuf));
680468b4841Sthorpej 		MEMCPY(BUFFER(ivec), BUFFER(encbuf), 8);
681468b4841Sthorpej 	}
682468b4841Sthorpej 	/*
683468b4841Sthorpej 	 * now compute the last one, right padding with '\0' if need be
684468b4841Sthorpej 	 */
685468b4841Sthorpej 	if (n > 0) {
686468b4841Sthorpej 		MEMZERO(&CHAR(msgbuf, n), 8 - n);
687468b4841Sthorpej 		for (n = 0; n < 8; n++)
688468b4841Sthorpej 			CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
689468b4841Sthorpej 		DES_XFORM(UBUFFER(encbuf));
690468b4841Sthorpej 	}
691468b4841Sthorpej 	/*
692468b4841Sthorpej 	 * drop the bits
693468b4841Sthorpej 	 * we write chars until fewer than 7 bits,
694468b4841Sthorpej 	 * and then pad the last one with 0 bits
695468b4841Sthorpej 	 */
696468b4841Sthorpej 	for (n = 0; macbits > 7; n++, macbits -= 8)
697468b4841Sthorpej 		(void)putchar(CHAR(encbuf, n));
698468b4841Sthorpej 	if (macbits > 0) {
699468b4841Sthorpej 		CHAR(msgbuf, 0) = 0x00;
700468b4841Sthorpej 		for (j = 0; j < macbits; j++)
701468b4841Sthorpej 			CHAR(msgbuf, 0) |= (CHAR(encbuf, n)&bits[j]);
702468b4841Sthorpej 		(void)putchar(CHAR(msgbuf, 0));
703468b4841Sthorpej 	}
704468b4841Sthorpej }
705468b4841Sthorpej 
706468b4841Sthorpej /*
707468b4841Sthorpej  * This encrypts using the Cipher FeedBack mode of DES
708468b4841Sthorpej  */
709d9a44d71Sjoerg static void
cfbenc(void)71093bf7731Sthorpej cfbenc(void)
711468b4841Sthorpej {
712468b4841Sthorpej 	register int n;		/* number of bytes actually read */
713468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
714468b4841Sthorpej 	register int bn;	/* block number */
715468b4841Sthorpej 	char ibuf[8];		/* input buffer */
716468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
717468b4841Sthorpej 
718468b4841Sthorpej 	/*
719468b4841Sthorpej 	 * do things in bytes, not bits
720468b4841Sthorpej 	 */
721468b4841Sthorpej 	nbytes = fbbits / 8;
722468b4841Sthorpej 	/*
723468b4841Sthorpej 	 * do the transformation
724468b4841Sthorpej 	 */
725468b4841Sthorpej 	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
726468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
727468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
728468b4841Sthorpej 		for (n = 0; n < 8 - nbytes; n++)
729468b4841Sthorpej 			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
730468b4841Sthorpej 		for (n = 0; n < nbytes; n++)
731468b4841Sthorpej 			UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
732468b4841Sthorpej 		WRITE(&CHAR(ivec, 8-nbytes), nbytes);
733468b4841Sthorpej 	}
734468b4841Sthorpej 	/*
735468b4841Sthorpej 	 * at EOF or last block -- in either case, the last byte contains
736468b4841Sthorpej 	 * the character representation of the number of bytes in it
737468b4841Sthorpej 	 */
738468b4841Sthorpej 	bn++;
739468b4841Sthorpej 	MEMZERO(&ibuf[n], nbytes - n);
740468b4841Sthorpej 	ibuf[nbytes - 1] = n;
741468b4841Sthorpej 	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
742468b4841Sthorpej 	DES_XFORM(UBUFFER(msgbuf));
743468b4841Sthorpej 	for (n = 0; n < nbytes; n++)
744468b4841Sthorpej 		ibuf[n] ^= UCHAR(msgbuf, n);
745468b4841Sthorpej 	WRITE(ibuf, nbytes);
746468b4841Sthorpej }
747468b4841Sthorpej 
748468b4841Sthorpej /*
749468b4841Sthorpej  * This decrypts using the Cipher Block Chaining mode of DES
750468b4841Sthorpej  */
751d9a44d71Sjoerg static void
cfbdec(void)75293bf7731Sthorpej cfbdec(void)
753468b4841Sthorpej {
754468b4841Sthorpej 	register int n;		/* number of bytes actually read */
755468b4841Sthorpej 	register int c;		/* used to test for EOF */
756468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
757468b4841Sthorpej 	register int bn;	/* block number */
758468b4841Sthorpej 	char ibuf[8];		/* input buffer */
759468b4841Sthorpej 	char obuf[8];		/* output buffer */
760468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
761468b4841Sthorpej 
762468b4841Sthorpej 	/*
763468b4841Sthorpej 	 * do things in bytes, not bits
764468b4841Sthorpej 	 */
765468b4841Sthorpej 	nbytes = fbbits / 8;
766468b4841Sthorpej 	/*
767468b4841Sthorpej 	 * do the transformation
768468b4841Sthorpej 	 */
769468b4841Sthorpej 	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
770468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
771468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
772468b4841Sthorpej 		for (c = 0; c < 8 - nbytes; c++)
773468b4841Sthorpej 			CHAR(ivec, c) = CHAR(ivec, c+nbytes);
774468b4841Sthorpej 		for (c = 0; c < nbytes; c++) {
775468b4841Sthorpej 			CHAR(ivec, 8-nbytes+c) = ibuf[c];
776468b4841Sthorpej 			obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
777468b4841Sthorpej 		}
778468b4841Sthorpej 		/*
779468b4841Sthorpej 		 * if the last one, handle it specially
780468b4841Sthorpej 		 */
781468b4841Sthorpej 		if ((c = getchar()) == EOF) {
782468b4841Sthorpej 			n = obuf[nbytes-1];
783468b4841Sthorpej 			if (n < 0 || n > nbytes-1)
78493bf7731Sthorpej 				bdes_err(bn,
78593bf7731Sthorpej 				    "decryption failed (block corrupted)");
786468b4841Sthorpej 		}
787468b4841Sthorpej 		else
788468b4841Sthorpej 			(void)ungetc(c, stdin);
789468b4841Sthorpej 		WRITE(obuf, n);
790468b4841Sthorpej 	}
791468b4841Sthorpej 	if (n > 0)
79293bf7731Sthorpej 		bdes_err(bn, "decryption failed (incomplete block)");
793468b4841Sthorpej }
794468b4841Sthorpej 
795468b4841Sthorpej /*
796468b4841Sthorpej  * This encrypts using the alternative Cipher FeedBack mode of DES
797468b4841Sthorpej  */
798d9a44d71Sjoerg static void
cfbaenc(void)79993bf7731Sthorpej cfbaenc(void)
800468b4841Sthorpej {
801468b4841Sthorpej 	register int n;		/* number of bytes actually read */
802468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
803468b4841Sthorpej 	register int bn;	/* block number */
804468b4841Sthorpej 	char ibuf[8];		/* input buffer */
805468b4841Sthorpej 	char obuf[8];		/* output buffer */
806468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
807468b4841Sthorpej 
808468b4841Sthorpej 	/*
809468b4841Sthorpej 	 * do things in bytes, not bits
810468b4841Sthorpej 	 */
811468b4841Sthorpej 	nbytes = fbbits / 7;
812468b4841Sthorpej 	/*
813468b4841Sthorpej 	 * do the transformation
814468b4841Sthorpej 	 */
815468b4841Sthorpej 	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
816468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
817468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
818468b4841Sthorpej 		for (n = 0; n < 8 - nbytes; n++)
819468b4841Sthorpej 			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
820468b4841Sthorpej 		for (n = 0; n < nbytes; n++)
821468b4841Sthorpej 			UCHAR(ivec, 8-nbytes+n) = (ibuf[n] ^ UCHAR(msgbuf, n))
822468b4841Sthorpej 							|0200;
823468b4841Sthorpej 		for (n = 0; n < nbytes; n++)
824468b4841Sthorpej 			obuf[n] = CHAR(ivec, 8-nbytes+n)&0177;
825468b4841Sthorpej 		WRITE(obuf, nbytes);
826468b4841Sthorpej 	}
827468b4841Sthorpej 	/*
828468b4841Sthorpej 	 * at EOF or last block -- in either case, the last byte contains
829468b4841Sthorpej 	 * the character representation of the number of bytes in it
830468b4841Sthorpej 	 */
831468b4841Sthorpej 	bn++;
832468b4841Sthorpej 	MEMZERO(&ibuf[n], nbytes - n);
833468b4841Sthorpej 	ibuf[nbytes - 1] = ('0' + n)|0200;
834468b4841Sthorpej 	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
835468b4841Sthorpej 	DES_XFORM(UBUFFER(msgbuf));
836468b4841Sthorpej 	for (n = 0; n < nbytes; n++)
837468b4841Sthorpej 		ibuf[n] ^= UCHAR(msgbuf, n);
838468b4841Sthorpej 	WRITE(ibuf, nbytes);
839468b4841Sthorpej }
840468b4841Sthorpej 
841468b4841Sthorpej /*
842468b4841Sthorpej  * This decrypts using the alternative Cipher Block Chaining mode of DES
843468b4841Sthorpej  */
844d9a44d71Sjoerg static void
cfbadec(void)84593bf7731Sthorpej cfbadec(void)
846468b4841Sthorpej {
847468b4841Sthorpej 	register int n;		/* number of bytes actually read */
848468b4841Sthorpej 	register int c;		/* used to test for EOF */
849468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
850468b4841Sthorpej 	register int bn;	/* block number */
851468b4841Sthorpej 	char ibuf[8];		/* input buffer */
852468b4841Sthorpej 	char obuf[8];		/* output buffer */
853468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
854468b4841Sthorpej 
855468b4841Sthorpej 	/*
856468b4841Sthorpej 	 * do things in bytes, not bits
857468b4841Sthorpej 	 */
858468b4841Sthorpej 	nbytes = fbbits / 7;
859468b4841Sthorpej 	/*
860468b4841Sthorpej 	 * do the transformation
861468b4841Sthorpej 	 */
862468b4841Sthorpej 	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
863468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
864468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
865468b4841Sthorpej 		for (c = 0; c < 8 - nbytes; c++)
866468b4841Sthorpej 			CHAR(ivec, c) = CHAR(ivec, c+nbytes);
867468b4841Sthorpej 		for (c = 0; c < nbytes; c++) {
868468b4841Sthorpej 			CHAR(ivec, 8-nbytes+c) = ibuf[c]|0200;
869468b4841Sthorpej 			obuf[c] = (ibuf[c] ^ UCHAR(msgbuf, c))&0177;
870468b4841Sthorpej 		}
871468b4841Sthorpej 		/*
872468b4841Sthorpej 		 * if the last one, handle it specially
873468b4841Sthorpej 		 */
874468b4841Sthorpej 		if ((c = getchar()) == EOF) {
875468b4841Sthorpej 			if ((n = (obuf[nbytes-1] - '0')) < 0
876468b4841Sthorpej 						|| n > nbytes-1)
87793bf7731Sthorpej 				bdes_err(bn,
87893bf7731Sthorpej 				    "decryption failed (block corrupted)");
879468b4841Sthorpej 		}
880468b4841Sthorpej 		else
881468b4841Sthorpej 			(void)ungetc(c, stdin);
882468b4841Sthorpej 		WRITE(obuf, n);
883468b4841Sthorpej 	}
884468b4841Sthorpej 	if (n > 0)
88593bf7731Sthorpej 		bdes_err(bn, "decryption failed (incomplete block)");
886468b4841Sthorpej }
887468b4841Sthorpej 
888468b4841Sthorpej 
889468b4841Sthorpej /*
890468b4841Sthorpej  * This encrypts using the Output FeedBack mode of DES
891468b4841Sthorpej  */
892d9a44d71Sjoerg static void
ofbenc(void)89393bf7731Sthorpej ofbenc(void)
894468b4841Sthorpej {
895468b4841Sthorpej 	register int n;		/* number of bytes actually read */
896468b4841Sthorpej 	register int c;		/* used to test for EOF */
897468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
898468b4841Sthorpej 	register int bn;	/* block number */
899468b4841Sthorpej 	char ibuf[8];		/* input buffer */
900468b4841Sthorpej 	char obuf[8];		/* output buffer */
901468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
902468b4841Sthorpej 
903468b4841Sthorpej 	/*
904468b4841Sthorpej 	 * do things in bytes, not bits
905468b4841Sthorpej 	 */
906468b4841Sthorpej 	nbytes = fbbits / 8;
907468b4841Sthorpej 	/*
908468b4841Sthorpej 	 * do the transformation
909468b4841Sthorpej 	 */
910468b4841Sthorpej 	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
911468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
912468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
913468b4841Sthorpej 		for (n = 0; n < 8 - nbytes; n++)
914468b4841Sthorpej 			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
915468b4841Sthorpej 		for (n = 0; n < nbytes; n++) {
916468b4841Sthorpej 			UCHAR(ivec, 8-nbytes+n) = UCHAR(msgbuf, n);
917468b4841Sthorpej 			obuf[n] = ibuf[n] ^ UCHAR(msgbuf, n);
918468b4841Sthorpej 		}
919468b4841Sthorpej 		WRITE(obuf, nbytes);
920468b4841Sthorpej 	}
921468b4841Sthorpej 	/*
922468b4841Sthorpej 	 * at EOF or last block -- in either case, the last byte contains
923468b4841Sthorpej 	 * the character representation of the number of bytes in it
924468b4841Sthorpej 	 */
925468b4841Sthorpej 	bn++;
926468b4841Sthorpej 	MEMZERO(&ibuf[n], nbytes - n);
927468b4841Sthorpej 	ibuf[nbytes - 1] = n;
928468b4841Sthorpej 	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
929468b4841Sthorpej 	DES_XFORM(UBUFFER(msgbuf));
930468b4841Sthorpej 	for (c = 0; c < nbytes; c++)
931468b4841Sthorpej 		ibuf[c] ^= UCHAR(msgbuf, c);
932468b4841Sthorpej 	WRITE(ibuf, nbytes);
933468b4841Sthorpej }
934468b4841Sthorpej 
935468b4841Sthorpej /*
936468b4841Sthorpej  * This decrypts using the Output Block Chaining mode of DES
937468b4841Sthorpej  */
938d9a44d71Sjoerg static void
ofbdec(void)93993bf7731Sthorpej ofbdec(void)
940468b4841Sthorpej {
941468b4841Sthorpej 	register int n;		/* number of bytes actually read */
942468b4841Sthorpej 	register int c;		/* used to test for EOF */
943468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
944468b4841Sthorpej 	register int bn;	/* block number */
945468b4841Sthorpej 	char ibuf[8];		/* input buffer */
946468b4841Sthorpej 	char obuf[8];		/* output buffer */
947468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
948468b4841Sthorpej 
949468b4841Sthorpej 	/*
950468b4841Sthorpej 	 * do things in bytes, not bits
951468b4841Sthorpej 	 */
952468b4841Sthorpej 	nbytes = fbbits / 8;
953468b4841Sthorpej 	/*
954468b4841Sthorpej 	 * do the transformation
955468b4841Sthorpej 	 */
956468b4841Sthorpej 	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
957468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
958468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
959468b4841Sthorpej 		for (c = 0; c < 8 - nbytes; c++)
960468b4841Sthorpej 			CHAR(ivec, c) = CHAR(ivec, c+nbytes);
961468b4841Sthorpej 		for (c = 0; c < nbytes; c++) {
962468b4841Sthorpej 			CHAR(ivec, 8-nbytes+c) = UCHAR(msgbuf, c);
963468b4841Sthorpej 			obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
964468b4841Sthorpej 		}
965468b4841Sthorpej 		/*
966468b4841Sthorpej 		 * if the last one, handle it specially
967468b4841Sthorpej 		 */
968468b4841Sthorpej 		if ((c = getchar()) == EOF) {
969468b4841Sthorpej 			n = obuf[nbytes-1];
970468b4841Sthorpej 			if (n < 0 || n > nbytes-1)
97193bf7731Sthorpej 				bdes_err(bn,
97293bf7731Sthorpej 				    "decryption failed (block corrupted)");
973468b4841Sthorpej 		}
974468b4841Sthorpej 		else
975468b4841Sthorpej 			(void)ungetc(c, stdin);
976468b4841Sthorpej 		/*
977468b4841Sthorpej 		 * dump it
978468b4841Sthorpej 		 */
979468b4841Sthorpej 		WRITE(obuf, n);
980468b4841Sthorpej 	}
981468b4841Sthorpej 	if (n > 0)
98293bf7731Sthorpej 		bdes_err(bn, "decryption failed (incomplete block)");
983468b4841Sthorpej }
984468b4841Sthorpej 
985468b4841Sthorpej /*
986468b4841Sthorpej  * This authenticates using the Cipher FeedBack mode of DES
987468b4841Sthorpej  */
988d9a44d71Sjoerg static void
cfbauth(void)98993bf7731Sthorpej cfbauth(void)
990468b4841Sthorpej {
991468b4841Sthorpej 	register int n, j;	/* number of bytes actually read */
992468b4841Sthorpej 	register int nbytes;	/* number of bytes to read */
993468b4841Sthorpej 	char ibuf[8];		/* input buffer */
994468b4841Sthorpej 	Desbuf msgbuf;		/* encryption buffer */
995468b4841Sthorpej 
996468b4841Sthorpej 	/*
997468b4841Sthorpej 	 * do things in bytes, not bits
998468b4841Sthorpej 	 */
999468b4841Sthorpej 	nbytes = fbbits / 8;
1000468b4841Sthorpej 	/*
1001468b4841Sthorpej 	 * do the transformation
1002468b4841Sthorpej 	 */
1003468b4841Sthorpej 	while ((n = READ(ibuf, nbytes)) == nbytes) {
1004468b4841Sthorpej 		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1005468b4841Sthorpej 		DES_XFORM(UBUFFER(msgbuf));
1006468b4841Sthorpej 		for (n = 0; n < 8 - nbytes; n++)
1007468b4841Sthorpej 			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
1008468b4841Sthorpej 		for (n = 0; n < nbytes; n++)
1009468b4841Sthorpej 			UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
1010468b4841Sthorpej 	}
1011468b4841Sthorpej 	/*
1012468b4841Sthorpej 	 * at EOF or last block -- in either case, the last byte contains
1013468b4841Sthorpej 	 * the character representation of the number of bytes in it
1014468b4841Sthorpej 	 */
1015468b4841Sthorpej 	MEMZERO(&ibuf[n], nbytes - n);
1016468b4841Sthorpej 	ibuf[nbytes - 1] = '0' + n;
1017468b4841Sthorpej 	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1018468b4841Sthorpej 	DES_XFORM(UBUFFER(msgbuf));
1019468b4841Sthorpej 	for (n = 0; n < nbytes; n++)
1020468b4841Sthorpej 		ibuf[n] ^= UCHAR(msgbuf, n);
1021468b4841Sthorpej 	/*
1022468b4841Sthorpej 	 * drop the bits
1023468b4841Sthorpej 	 * we write chars until fewer than 7 bits,
1024468b4841Sthorpej 	 * and then pad the last one with 0 bits
1025468b4841Sthorpej 	 */
1026468b4841Sthorpej 	for (n = 0; macbits > 7; n++, macbits -= 8)
1027468b4841Sthorpej 		(void)putchar(CHAR(msgbuf, n));
1028468b4841Sthorpej 	if (macbits > 0) {
1029468b4841Sthorpej 		CHAR(msgbuf, 0) = 0x00;
1030468b4841Sthorpej 		for (j = 0; j < macbits; j++)
1031468b4841Sthorpej 			CHAR(msgbuf, 0) |= (CHAR(msgbuf, n)&bits[j]);
1032468b4841Sthorpej 		(void)putchar(CHAR(msgbuf, 0));
1033468b4841Sthorpej 	}
1034468b4841Sthorpej }
1035468b4841Sthorpej 
1036468b4841Sthorpej #ifndef FASTWAY
1037468b4841Sthorpej /*
1038468b4841Sthorpej  * change from 8 bits/Uchar to 1 bit/Uchar
1039468b4841Sthorpej  */
1040d9a44d71Sjoerg static void
expand(Desbuf from,char * to)104193bf7731Sthorpej expand(Desbuf from, char *to)
1042468b4841Sthorpej {
1043468b4841Sthorpej 	register int i, j;		/* counters in for loop */
1044468b4841Sthorpej 
1045468b4841Sthorpej 	for (i = 0; i < 8; i++)
1046468b4841Sthorpej 		for (j = 0; j < 8; j++)
1047468b4841Sthorpej 			*to++ = (CHAR(from, i)>>(7-j))&01;
1048468b4841Sthorpej }
1049468b4841Sthorpej 
1050468b4841Sthorpej /*
1051468b4841Sthorpej  * change from 1 bit/char to 8 bits/Uchar
1052468b4841Sthorpej  */
1053d9a44d71Sjoerg static void
compress(char * from,Desbuf to)105493bf7731Sthorpej compress(char *from, Desbuf to)
1055468b4841Sthorpej {
1056468b4841Sthorpej 	register int i, j;		/* counters in for loop */
1057468b4841Sthorpej 
1058468b4841Sthorpej 	for (i = 0; i < 8; i++) {
1059468b4841Sthorpej 	 	CHAR(to, i) = 0;
1060468b4841Sthorpej 		for (j = 0; j < 8; j++)
1061468b4841Sthorpej 			CHAR(to, i) = ((*from++)<<(7-j))|CHAR(to, i);
1062468b4841Sthorpej 	}
1063468b4841Sthorpej }
1064468b4841Sthorpej #endif
1065468b4841Sthorpej 
1066468b4841Sthorpej /*
1067468b4841Sthorpej  * message about usage
1068468b4841Sthorpej  */
1069d9a44d71Sjoerg static void
usage(void)107093bf7731Sthorpej usage(void)
1071468b4841Sthorpej {
107293bf7731Sthorpej 
1073a8ec668dScgd 	(void) fprintf(stderr, "usage: %s %s\n", getprogname(),
107493bf7731Sthorpej 	    "[-abdp] [-F bit] [-f bit] [-k key] [-m bit] [-o bit] [-v vector]");
1075468b4841Sthorpej 	exit(1);
1076468b4841Sthorpej }
1077