1/*	$NetBSD: bdes.c,v 1.11 2023/06/27 19:30:27 andvar Exp $	*/
2
3/*-
4 * Copyright (c) 1991, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Matt Bishop of Dartmouth College.
9 *
10 * The United States Government has rights in this work pursuant
11 * to contract no. NAG 2-680 between the National Aeronautics and
12 * Space Administration and Dartmouth College.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#include <sys/cdefs.h>
40#ifndef lint
41__COPYRIGHT("@(#) Copyright (c) 1991, 1993\
42 The Regents of the University of California.  All rights reserved.");
43#endif /* not lint */
44
45#ifndef lint
46#if 0
47static char sccsid[] = "@(#)bdes.c	8.1 (Berkeley) 6/6/93";
48#else
49__RCSID("$NetBSD: bdes.c,v 1.11 2023/06/27 19:30:27 andvar Exp $");
50#endif
51#endif /* not lint */
52
53/*
54 * BDES -- DES encryption package for Berkeley Software Distribution 4.4
55 * options:
56 *	-a	key is in ASCII
57 *	-b	use ECB (electronic code book) mode
58 *	-d	invert (decrypt) input
59 *	-f b	use b-bit CFB (cipher feedback) mode
60 *	-F b	use b-bit CFB (cipher feedback) alternative mode
61 *	-k key	use key as the cryptographic key
62 *	-m b	generate a MAC of length b
63 *	-o b	use b-bit OFB (output feedback) mode
64 *	-p	don't reset the parity bit
65 *	-v v	use v as the initialization vector (ignored for ECB)
66 * note: the last character of the last block is the integer indicating
67 * how many characters of that block are to be output
68 *
69 * Author: Matt Bishop
70 *	   Department of Mathematics and Computer Science
71 *	   Dartmouth College
72 *	   Hanover, NH  03755
73 * Email:  Matt.Bishop@dartmouth.edu
74 *	   ...!decvax!dartvax!Matt.Bishop
75 *
76 * See Technical Report PCS-TR91-158, Department of Mathematics and Computer
77 * Science, Dartmouth College, for a detailed description of the implemen-
78 * tation and differences between it and Sun's.  The DES is described in
79 * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page
80 * or the technical report for a complete reference).
81 */
82
83#include <errno.h>
84#include <unistd.h>
85#include <stdio.h>
86#include <ctype.h>
87#include <stdlib.h>
88#include <string.h>
89
90/*
91 * BSD and System V systems offer special library calls that do
92 * block moves and fills, so if possible we take advantage of them
93 */
94#define	MEMCPY(dest,src,len)	bcopy((src),(dest),(len))
95#define	MEMZERO(dest,len)	bzero((dest),(len))
96
97/* Hide the calls to the primitive encryption routines. */
98#define	FASTWAY
99#ifdef	FASTWAY
100#define	DES_KEY(buf) \
101	if (des_setkey(buf)) \
102		bdes_err(0, "des_setkey");
103#define	DES_XFORM(buf) \
104	if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
105		bdes_err(0, "des_cipher");
106#else
107#define	DES_KEY(buf)	{						\
108				char bits1[64];	/* bits of key */	\
109				expand(buf, bits1);			\
110				if (setkey(bits1))			\
111					bdes_err(0, "setkey");		\
112			}
113#define	DES_XFORM(buf)	{						\
114				char bits1[64];	/* bits of message */	\
115				expand(buf, bits1);			\
116				if (encrypt(bits1, inverse))		\
117					bdes_err(0, "encrypt");		\
118				compress(bits1, buf);			\
119			}
120#endif
121
122/*
123 * this does an error-checking write
124 */
125#define	READ(buf, n)	fread(buf, sizeof(char), n, stdin)
126#define WRITE(buf,n)						\
127		if (fwrite(buf, sizeof(char), n, stdout) != (size_t)n)	\
128			bdes_err(bn, NULL);
129
130/*
131 * some things to make references easier
132 */
133typedef char Desbuf[8];
134#define	CHAR(x,i)	(x[i])
135#define	UCHAR(x,i)	(x[i])
136#define	BUFFER(x)	(x)
137#define	UBUFFER(x)	(x)
138
139/*
140 * global variables and related macros
141 */
142#define KEY_DEFAULT		0	/* interpret radix of key from key */
143#define KEY_ASCII		1	/* key is in ASCII characters */
144static int keybase = KEY_DEFAULT;	/* how to interpret the key */
145
146static enum { 				/* encrypt, decrypt, authenticate */
147	MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
148} mode = MODE_ENCRYPT;
149static enum {				/* ecb, cbc, cfb, cfba, ofb? */
150	ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
151} alg = ALG_CBC;
152
153static Desbuf ivec;				/* initialization vector */
154static const char bits[] = {				/* used to extract bits from a char */
155	'\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
156};
157static int inverse;				/* 0 to encrypt, 1 to decrypt */
158static int macbits = -1;			/* number of bits in authentication */
159static int fbbits = -1;			/* number of feedback bits */
160static int pflag;				/* 1 to preserve parity bits */
161
162static int	setbits(char *, int);
163static void	bdes_err(int, const char *) __dead;
164static int	tobinhex(char, int);
165static void	cvtkey(char *, char *);
166static void	makekey(Desbuf);
167static void	ecbenc(void);
168static void	ecbdec(void);
169static void	cbcenc(void);
170static void	cbcdec(void);
171static void	cbcauth(void);
172static void	cfbenc(void);
173static void	cfbdec(void);
174static void	cfbaenc(void);
175static void	cfbadec(void);
176static void	ofbenc(void);
177static void	ofbdec(void);
178static void	cfbauth(void);
179#ifndef FASTWAY
180static void	expand(Desbuf, char *);
181static void	compress(char *, Desbuf);
182#endif
183static void	usage(void) __dead;
184
185int
186main(int ac, char *av[])
187{
188	register int i;			/* counter in a for loop */
189	register char *p;		/* used to obtain the key */
190	Desbuf msgbuf;			/* I/O buffer */
191	int kflag;			/* command-line encryption key */
192	int argc;			/* the real arg count */
193	char **argv;			/* the real argument vector */
194
195	/*
196	 * Hide the arguments from ps(1) by making private copies of them
197	 * and clobbering the global (visible to ps(1)) ones.
198	 */
199	argc = ac;
200	ac = 1;
201	argv = malloc((argc + 1) * sizeof(char *));
202	for (i = 0; i < argc; ++i) {
203		argv[i] = strdup(av[i]);
204		MEMZERO(av[i], strlen(av[i]));
205	}
206	argv[argc] = NULL;
207
208	/* initialize the initialization vctor */
209	MEMZERO(ivec, 8);
210
211	/* process the argument list */
212	kflag = 0;
213	while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1)
214		switch(i) {
215		case 'a':		/* key is ASCII */
216			keybase = KEY_ASCII;
217			break;
218		case 'b':		/* use ECB mode */
219			alg = ALG_ECB;
220			break;
221		case 'd':		/* decrypt */
222			mode = MODE_DECRYPT;
223			break;
224		case 'F':		/* use alternative CFB mode */
225			alg = ALG_CFBA;
226			if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0)
227				bdes_err(-1,
228				    "-F: number must be 1-56 inclusive");
229			else if (fbbits == -1)
230				bdes_err(-1,
231				    "-F: number must be a multiple of 7");
232			break;
233		case 'f':		/* use CFB mode */
234			alg = ALG_CFB;
235			if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
236				bdes_err(-1,
237				    "-f: number must be 1-64 inclusive");
238			else if (fbbits == -1)
239				bdes_err(-1,
240				    "-f: number must be a multiple of 8");
241			break;
242		case 'k':		/* encryption key */
243			kflag = 1;
244			cvtkey(BUFFER(msgbuf), optarg);
245			break;
246		case 'm':		/* number of bits for MACing */
247			mode = MODE_AUTHENTICATE;
248			if ((macbits = setbits(optarg, 1)) > 64)
249				bdes_err(-1,
250				    "-m: number must be 0-64 inclusive");
251			break;
252		case 'o':		/* use OFB mode */
253			alg = ALG_OFB;
254			if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
255				bdes_err(-1,
256				    "-o: number must be 1-64 inclusive");
257			else if (fbbits == -1)
258				bdes_err(-1,
259				    "-o: number must be a multiple of 8");
260			break;
261		case 'p':		/* preserve parity bits */
262			pflag = 1;
263			break;
264		case 'v':		/* set initialization vector */
265			cvtkey(BUFFER(ivec), optarg);
266			break;
267		default:		/* error */
268			usage();
269		}
270
271	if (!kflag) {
272		/*
273		 * if the key's not ASCII, assume it is
274		 */
275		keybase = KEY_ASCII;
276		/*
277		 * get the key
278		 */
279		p = getpass("Enter key: ");
280		/*
281		 * copy it, nul-padded, into the key area
282		 */
283		cvtkey(BUFFER(msgbuf), p);
284	}
285
286	makekey(msgbuf);
287	inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT;
288
289	switch(alg) {
290	case ALG_CBC:
291		switch(mode) {
292		case MODE_AUTHENTICATE:	/* authenticate using CBC mode */
293			cbcauth();
294			break;
295		case MODE_DECRYPT:	/* decrypt using CBC mode */
296			cbcdec();
297			break;
298		case MODE_ENCRYPT:	/* encrypt using CBC mode */
299			cbcenc();
300			break;
301		}
302		break;
303	case ALG_CFB:
304		switch(mode) {
305		case MODE_AUTHENTICATE:	/* authenticate using CFB mode */
306			cfbauth();
307			break;
308		case MODE_DECRYPT:	/* decrypt using CFB mode */
309			cfbdec();
310			break;
311		case MODE_ENCRYPT:	/* encrypt using CFB mode */
312			cfbenc();
313			break;
314		}
315		break;
316	case ALG_CFBA:
317		switch(mode) {
318		case MODE_AUTHENTICATE:	/* authenticate using CFBA mode */
319			bdes_err(-1, "can't authenticate with CFBA mode");
320			break;
321		case MODE_DECRYPT:	/* decrypt using CFBA mode */
322			cfbadec();
323			break;
324		case MODE_ENCRYPT:	/* encrypt using CFBA mode */
325			cfbaenc();
326			break;
327		}
328		break;
329	case ALG_ECB:
330		switch(mode) {
331		case MODE_AUTHENTICATE:	/* authenticate using ECB mode */
332			bdes_err(-1, "can't authenticate with ECB mode");
333			break;
334		case MODE_DECRYPT:	/* decrypt using ECB mode */
335			ecbdec();
336			break;
337		case MODE_ENCRYPT:	/* encrypt using ECB mode */
338			ecbenc();
339			break;
340		}
341		break;
342	case ALG_OFB:
343		switch(mode) {
344		case MODE_AUTHENTICATE:	/* authenticate using OFB mode */
345			bdes_err(-1, "can't authenticate with OFB mode");
346			break;
347		case MODE_DECRYPT:	/* decrypt using OFB mode */
348			ofbdec();
349			break;
350		case MODE_ENCRYPT:	/* encrypt using OFB mode */
351			ofbenc();
352			break;
353		}
354		break;
355	}
356	exit(0);
357}
358
359/*
360 * print a warning message and, possibly, terminate
361 */
362static void
363bdes_err(int n, const char *s)
364{
365	if (n > 0)
366		(void)fprintf(stderr, "bdes (block %d): ", n);
367	else
368		(void)fprintf(stderr, "bdes: ");
369	(void)fprintf(stderr, "%s\n", s ? s : strerror(errno));
370	exit(1);
371}
372
373/*
374 * map a hex character to an integer
375 */
376static int
377tobinhex(char c, int radix)
378{
379	switch(c) {
380	case '0':		return(0x0);
381	case '1':		return(0x1);
382	case '2':		return(radix > 2 ? 0x2 : -1);
383	case '3':		return(radix > 3 ? 0x3 : -1);
384	case '4':		return(radix > 4 ? 0x4 : -1);
385	case '5':		return(radix > 5 ? 0x5 : -1);
386	case '6':		return(radix > 6 ? 0x6 : -1);
387	case '7':		return(radix > 7 ? 0x7 : -1);
388	case '8':		return(radix > 8 ? 0x8 : -1);
389	case '9':		return(radix > 9 ? 0x9 : -1);
390	case 'A': case 'a':	return(radix > 10 ? 0xa : -1);
391	case 'B': case 'b':	return(radix > 11 ? 0xb : -1);
392	case 'C': case 'c':	return(radix > 12 ? 0xc : -1);
393	case 'D': case 'd':	return(radix > 13 ? 0xd : -1);
394	case 'E': case 'e':	return(radix > 14 ? 0xe : -1);
395	case 'F': case 'f':	return(radix > 15 ? 0xf : -1);
396	}
397	/*
398	 * invalid character
399	 */
400	return(-1);
401}
402
403/*
404 * convert the key to a bit pattern
405 */
406static void
407cvtkey(char *obuf, char *ibuf)
408{
409	register int i, j;		/* counter in a for loop */
410	int nbuf[64];			/* used for hex/key translation */
411
412	/*
413	 * just switch on the key base
414	 */
415	switch(keybase) {
416	case KEY_ASCII:			/* ascii to integer */
417		(void)strncpy(obuf, ibuf, 8);
418		return;
419	case KEY_DEFAULT:		/* tell from context */
420		/*
421		 * leading '0x' or '0X' == hex key
422		 */
423		if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) {
424			ibuf = &ibuf[2];
425			/*
426			 * now translate it, bombing on any illegal hex digit
427			 */
428			for (i = 0; i < 16 && ibuf[i]; i++)
429				if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1)
430					bdes_err(-1, "bad hex digit in key");
431			while (i < 16)
432				nbuf[i++] = 0;
433			for (i = 0; i < 8; i++)
434				obuf[i] =
435				    ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
436			/* preserve parity bits */
437			pflag = 1;
438			return;
439		}
440		/*
441		 * leading '0b' or '0B' == binary key
442		 */
443		if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) {
444			ibuf = &ibuf[2];
445			/*
446			 * now translate it, bombing on any illegal binary digit
447			 */
448			for (i = 0; ibuf[i] && i < 16; i++)
449				if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1)
450					bdes_err(-1, "bad binary digit in key");
451			while (i < 64)
452				nbuf[i++] = 0;
453			for (i = 0; i < 8; i++)
454				for (j = 0; j < 8; j++)
455					obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
456			/* preserve parity bits */
457			pflag = 1;
458			return;
459		}
460		/*
461		 * no special leader -- ASCII
462		 */
463		(void)strncpy(obuf, ibuf, 8);
464	}
465}
466
467/*
468 * convert an ASCII string into a decimal number:
469 * 1. must be between 0 and 64 inclusive (or 56, checked by caller)
470 * 2. must be a valid decimal number
471 * 3. must be a multiple of mult
472 */
473static int
474setbits(char *s, int mult)
475{
476	char *p;
477	int n;		/* the integer collected */
478
479	n = strtoul(s, &p, 10);
480	if (*p != 0)
481		bdes_err(-1, "bad decimal digit in MAC length");
482	/*
483	 * be sure it's a multiple of mult
484	 */
485	return((n % mult != 0) ? -1 : n);
486}
487
488/*****************
489 * DES FUNCTIONS *
490 *****************/
491/*
492 * This sets the DES key and (if you're using the deszip version)
493 * the direction of the transformation.  This uses the Sun
494 * to map the 64-bit key onto the 56 bits that the key schedule
495 * generation routines use: the old way, which just uses the user-
496 * supplied 64 bits as is, and the new way, which resets the parity
497 * bit to be the same as the low-order bit in each character.  The
498 * new way generates a greater variety of key schedules, since many
499 * systems set the parity (high) bit of each character to 0, and the
500 * DES ignores the low order bit of each character.
501 */
502static void
503makekey(Desbuf buf)
504{
505	register int i, j;			/* counter in a for loop */
506	register int par;			/* parity counter */
507
508	/*
509	 * if the parity is not preserved, flip it
510	 */
511	if (!pflag) {
512		for (i = 0; i < 8; i++) {
513			par = 0;
514			for (j = 1; j < 8; j++)
515				if ((bits[j]&UCHAR(buf, i)) != 0)
516					par++;
517			if ((par&01) == 01)
518				UCHAR(buf, i) = UCHAR(buf, i)&0177;
519			else
520				UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
521		}
522	}
523
524	DES_KEY(UBUFFER(buf));
525}
526
527/*
528 * This encrypts using the Electronic Code Book mode of DES
529 */
530static void
531ecbenc(void)
532{
533	register int n;		/* number of bytes actually read */
534	register int bn;	/* block number */
535	Desbuf msgbuf;		/* I/O buffer */
536
537	for (bn = 0; (n = READ(BUFFER(msgbuf),  8)) == 8; bn++) {
538		/*
539		 * do the transformation
540		 */
541		DES_XFORM(UBUFFER(msgbuf));
542		WRITE(BUFFER(msgbuf), 8);
543	}
544	/*
545	 * at EOF or last block -- in either ase, the last byte contains
546	 * the character representation of the number of bytes in it
547	 */
548	bn++;
549	MEMZERO(&CHAR(msgbuf, n), 8 - n);
550	CHAR(msgbuf, 7) = n;
551	DES_XFORM(UBUFFER(msgbuf));
552	WRITE(BUFFER(msgbuf), 8);
553
554}
555
556/*
557 * This decrypts using the Electronic Code Book mode of DES
558 */
559static void
560ecbdec(void)
561{
562	register int n;		/* number of bytes actually read */
563	register int c;		/* used to test for EOF */
564	register int bn;	/* block number */
565	Desbuf msgbuf;		/* I/O buffer */
566
567	for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
568		/*
569		 * do the transformation
570		 */
571		DES_XFORM(UBUFFER(msgbuf));
572		/*
573		 * if the last one, handle it specially
574		 */
575		if ((c = getchar()) == EOF) {
576			n = CHAR(msgbuf, 7);
577			if (n < 0 || n > 7)
578				bdes_err(bn,
579				    "decryption failed (block corrupted)");
580		}
581		else
582			(void)ungetc(c, stdin);
583		WRITE(BUFFER(msgbuf), n);
584	}
585	if (n > 0)
586		bdes_err(bn, "decryption failed (incomplete block)");
587}
588
589/*
590 * This encrypts using the Cipher Block Chaining mode of DES
591 */
592static void
593cbcenc(void)
594{
595	register int n;		/* number of bytes actually read */
596	register int bn;	/* block number */
597	Desbuf msgbuf;		/* I/O buffer */
598
599	/*
600	 * do the transformation
601	 */
602	for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
603		for (n = 0; n < 8; n++)
604			CHAR(msgbuf, n) ^= CHAR(ivec, n);
605		DES_XFORM(UBUFFER(msgbuf));
606		MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
607		WRITE(BUFFER(msgbuf), 8);
608	}
609	/*
610	 * at EOF or last block -- in either case, the last byte contains
611	 * the character representation of the number of bytes in it
612	 */
613	bn++;
614	MEMZERO(&CHAR(msgbuf, n), 8 - n);
615	CHAR(msgbuf, 7) = n;
616	for (n = 0; n < 8; n++)
617		CHAR(msgbuf, n) ^= CHAR(ivec, n);
618	DES_XFORM(UBUFFER(msgbuf));
619	WRITE(BUFFER(msgbuf), 8);
620
621}
622
623/*
624 * This decrypts using the Cipher Block Chaining mode of DES
625 */
626static void
627cbcdec(void)
628{
629	register int n;		/* number of bytes actually read */
630	Desbuf msgbuf;		/* I/O buffer */
631	Desbuf ibuf;		/* temp buffer for initialization vector */
632	register int c;		/* used to test for EOF */
633	register int bn;	/* block number */
634
635	for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
636		/*
637		 * do the transformation
638		 */
639		MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8);
640		DES_XFORM(UBUFFER(msgbuf));
641		for (c = 0; c < 8; c++)
642			UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
643		MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8);
644		/*
645		 * if the last one, handle it specially
646		 */
647		if ((c = getchar()) == EOF) {
648			n = CHAR(msgbuf, 7);
649			if (n < 0 || n > 7)
650				bdes_err(bn,
651				    "decryption failed (block corrupted)");
652		}
653		else
654			(void)ungetc(c, stdin);
655		WRITE(BUFFER(msgbuf), n);
656	}
657	if (n > 0)
658		bdes_err(bn, "decryption failed (incomplete block)");
659}
660
661/*
662 * This authenticates using the Cipher Block Chaining mode of DES
663 */
664static void
665cbcauth(void)
666{
667	register int n, j;		/* number of bytes actually read */
668	Desbuf msgbuf;		/* I/O buffer */
669	Desbuf encbuf;		/* encryption buffer */
670
671	/*
672	 * do the transformation
673	 * note we DISCARD the encrypted block;
674	 * we only care about the last one
675	 */
676	while ((n = READ(BUFFER(msgbuf), 8)) == 8) {
677		for (n = 0; n < 8; n++)
678			CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
679		DES_XFORM(UBUFFER(encbuf));
680		MEMCPY(BUFFER(ivec), BUFFER(encbuf), 8);
681	}
682	/*
683	 * now compute the last one, right padding with '\0' if need be
684	 */
685	if (n > 0) {
686		MEMZERO(&CHAR(msgbuf, n), 8 - n);
687		for (n = 0; n < 8; n++)
688			CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
689		DES_XFORM(UBUFFER(encbuf));
690	}
691	/*
692	 * drop the bits
693	 * we write chars until fewer than 7 bits,
694	 * and then pad the last one with 0 bits
695	 */
696	for (n = 0; macbits > 7; n++, macbits -= 8)
697		(void)putchar(CHAR(encbuf, n));
698	if (macbits > 0) {
699		CHAR(msgbuf, 0) = 0x00;
700		for (j = 0; j < macbits; j++)
701			CHAR(msgbuf, 0) |= (CHAR(encbuf, n)&bits[j]);
702		(void)putchar(CHAR(msgbuf, 0));
703	}
704}
705
706/*
707 * This encrypts using the Cipher FeedBack mode of DES
708 */
709static void
710cfbenc(void)
711{
712	register int n;		/* number of bytes actually read */
713	register int nbytes;	/* number of bytes to read */
714	register int bn;	/* block number */
715	char ibuf[8];		/* input buffer */
716	Desbuf msgbuf;		/* encryption buffer */
717
718	/*
719	 * do things in bytes, not bits
720	 */
721	nbytes = fbbits / 8;
722	/*
723	 * do the transformation
724	 */
725	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
726		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
727		DES_XFORM(UBUFFER(msgbuf));
728		for (n = 0; n < 8 - nbytes; n++)
729			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
730		for (n = 0; n < nbytes; n++)
731			UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
732		WRITE(&CHAR(ivec, 8-nbytes), nbytes);
733	}
734	/*
735	 * at EOF or last block -- in either case, the last byte contains
736	 * the character representation of the number of bytes in it
737	 */
738	bn++;
739	MEMZERO(&ibuf[n], nbytes - n);
740	ibuf[nbytes - 1] = n;
741	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
742	DES_XFORM(UBUFFER(msgbuf));
743	for (n = 0; n < nbytes; n++)
744		ibuf[n] ^= UCHAR(msgbuf, n);
745	WRITE(ibuf, nbytes);
746}
747
748/*
749 * This decrypts using the Cipher Block Chaining mode of DES
750 */
751static void
752cfbdec(void)
753{
754	register int n;		/* number of bytes actually read */
755	register int c;		/* used to test for EOF */
756	register int nbytes;	/* number of bytes to read */
757	register int bn;	/* block number */
758	char ibuf[8];		/* input buffer */
759	char obuf[8];		/* output buffer */
760	Desbuf msgbuf;		/* encryption buffer */
761
762	/*
763	 * do things in bytes, not bits
764	 */
765	nbytes = fbbits / 8;
766	/*
767	 * do the transformation
768	 */
769	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
770		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
771		DES_XFORM(UBUFFER(msgbuf));
772		for (c = 0; c < 8 - nbytes; c++)
773			CHAR(ivec, c) = CHAR(ivec, c+nbytes);
774		for (c = 0; c < nbytes; c++) {
775			CHAR(ivec, 8-nbytes+c) = ibuf[c];
776			obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
777		}
778		/*
779		 * if the last one, handle it specially
780		 */
781		if ((c = getchar()) == EOF) {
782			n = obuf[nbytes-1];
783			if (n < 0 || n > nbytes-1)
784				bdes_err(bn,
785				    "decryption failed (block corrupted)");
786		}
787		else
788			(void)ungetc(c, stdin);
789		WRITE(obuf, n);
790	}
791	if (n > 0)
792		bdes_err(bn, "decryption failed (incomplete block)");
793}
794
795/*
796 * This encrypts using the alternative Cipher FeedBack mode of DES
797 */
798static void
799cfbaenc(void)
800{
801	register int n;		/* number of bytes actually read */
802	register int nbytes;	/* number of bytes to read */
803	register int bn;	/* block number */
804	char ibuf[8];		/* input buffer */
805	char obuf[8];		/* output buffer */
806	Desbuf msgbuf;		/* encryption buffer */
807
808	/*
809	 * do things in bytes, not bits
810	 */
811	nbytes = fbbits / 7;
812	/*
813	 * do the transformation
814	 */
815	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
816		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
817		DES_XFORM(UBUFFER(msgbuf));
818		for (n = 0; n < 8 - nbytes; n++)
819			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
820		for (n = 0; n < nbytes; n++)
821			UCHAR(ivec, 8-nbytes+n) = (ibuf[n] ^ UCHAR(msgbuf, n))
822							|0200;
823		for (n = 0; n < nbytes; n++)
824			obuf[n] = CHAR(ivec, 8-nbytes+n)&0177;
825		WRITE(obuf, nbytes);
826	}
827	/*
828	 * at EOF or last block -- in either case, the last byte contains
829	 * the character representation of the number of bytes in it
830	 */
831	bn++;
832	MEMZERO(&ibuf[n], nbytes - n);
833	ibuf[nbytes - 1] = ('0' + n)|0200;
834	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
835	DES_XFORM(UBUFFER(msgbuf));
836	for (n = 0; n < nbytes; n++)
837		ibuf[n] ^= UCHAR(msgbuf, n);
838	WRITE(ibuf, nbytes);
839}
840
841/*
842 * This decrypts using the alternative Cipher Block Chaining mode of DES
843 */
844static void
845cfbadec(void)
846{
847	register int n;		/* number of bytes actually read */
848	register int c;		/* used to test for EOF */
849	register int nbytes;	/* number of bytes to read */
850	register int bn;	/* block number */
851	char ibuf[8];		/* input buffer */
852	char obuf[8];		/* output buffer */
853	Desbuf msgbuf;		/* encryption buffer */
854
855	/*
856	 * do things in bytes, not bits
857	 */
858	nbytes = fbbits / 7;
859	/*
860	 * do the transformation
861	 */
862	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
863		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
864		DES_XFORM(UBUFFER(msgbuf));
865		for (c = 0; c < 8 - nbytes; c++)
866			CHAR(ivec, c) = CHAR(ivec, c+nbytes);
867		for (c = 0; c < nbytes; c++) {
868			CHAR(ivec, 8-nbytes+c) = ibuf[c]|0200;
869			obuf[c] = (ibuf[c] ^ UCHAR(msgbuf, c))&0177;
870		}
871		/*
872		 * if the last one, handle it specially
873		 */
874		if ((c = getchar()) == EOF) {
875			if ((n = (obuf[nbytes-1] - '0')) < 0
876						|| n > nbytes-1)
877				bdes_err(bn,
878				    "decryption failed (block corrupted)");
879		}
880		else
881			(void)ungetc(c, stdin);
882		WRITE(obuf, n);
883	}
884	if (n > 0)
885		bdes_err(bn, "decryption failed (incomplete block)");
886}
887
888
889/*
890 * This encrypts using the Output FeedBack mode of DES
891 */
892static void
893ofbenc(void)
894{
895	register int n;		/* number of bytes actually read */
896	register int c;		/* used to test for EOF */
897	register int nbytes;	/* number of bytes to read */
898	register int bn;	/* block number */
899	char ibuf[8];		/* input buffer */
900	char obuf[8];		/* output buffer */
901	Desbuf msgbuf;		/* encryption buffer */
902
903	/*
904	 * do things in bytes, not bits
905	 */
906	nbytes = fbbits / 8;
907	/*
908	 * do the transformation
909	 */
910	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
911		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
912		DES_XFORM(UBUFFER(msgbuf));
913		for (n = 0; n < 8 - nbytes; n++)
914			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
915		for (n = 0; n < nbytes; n++) {
916			UCHAR(ivec, 8-nbytes+n) = UCHAR(msgbuf, n);
917			obuf[n] = ibuf[n] ^ UCHAR(msgbuf, n);
918		}
919		WRITE(obuf, nbytes);
920	}
921	/*
922	 * at EOF or last block -- in either case, the last byte contains
923	 * the character representation of the number of bytes in it
924	 */
925	bn++;
926	MEMZERO(&ibuf[n], nbytes - n);
927	ibuf[nbytes - 1] = n;
928	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
929	DES_XFORM(UBUFFER(msgbuf));
930	for (c = 0; c < nbytes; c++)
931		ibuf[c] ^= UCHAR(msgbuf, c);
932	WRITE(ibuf, nbytes);
933}
934
935/*
936 * This decrypts using the Output Block Chaining mode of DES
937 */
938static void
939ofbdec(void)
940{
941	register int n;		/* number of bytes actually read */
942	register int c;		/* used to test for EOF */
943	register int nbytes;	/* number of bytes to read */
944	register int bn;	/* block number */
945	char ibuf[8];		/* input buffer */
946	char obuf[8];		/* output buffer */
947	Desbuf msgbuf;		/* encryption buffer */
948
949	/*
950	 * do things in bytes, not bits
951	 */
952	nbytes = fbbits / 8;
953	/*
954	 * do the transformation
955	 */
956	for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
957		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
958		DES_XFORM(UBUFFER(msgbuf));
959		for (c = 0; c < 8 - nbytes; c++)
960			CHAR(ivec, c) = CHAR(ivec, c+nbytes);
961		for (c = 0; c < nbytes; c++) {
962			CHAR(ivec, 8-nbytes+c) = UCHAR(msgbuf, c);
963			obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
964		}
965		/*
966		 * if the last one, handle it specially
967		 */
968		if ((c = getchar()) == EOF) {
969			n = obuf[nbytes-1];
970			if (n < 0 || n > nbytes-1)
971				bdes_err(bn,
972				    "decryption failed (block corrupted)");
973		}
974		else
975			(void)ungetc(c, stdin);
976		/*
977		 * dump it
978		 */
979		WRITE(obuf, n);
980	}
981	if (n > 0)
982		bdes_err(bn, "decryption failed (incomplete block)");
983}
984
985/*
986 * This authenticates using the Cipher FeedBack mode of DES
987 */
988static void
989cfbauth(void)
990{
991	register int n, j;	/* number of bytes actually read */
992	register int nbytes;	/* number of bytes to read */
993	char ibuf[8];		/* input buffer */
994	Desbuf msgbuf;		/* encryption buffer */
995
996	/*
997	 * do things in bytes, not bits
998	 */
999	nbytes = fbbits / 8;
1000	/*
1001	 * do the transformation
1002	 */
1003	while ((n = READ(ibuf, nbytes)) == nbytes) {
1004		MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1005		DES_XFORM(UBUFFER(msgbuf));
1006		for (n = 0; n < 8 - nbytes; n++)
1007			UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
1008		for (n = 0; n < nbytes; n++)
1009			UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
1010	}
1011	/*
1012	 * at EOF or last block -- in either case, the last byte contains
1013	 * the character representation of the number of bytes in it
1014	 */
1015	MEMZERO(&ibuf[n], nbytes - n);
1016	ibuf[nbytes - 1] = '0' + n;
1017	MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1018	DES_XFORM(UBUFFER(msgbuf));
1019	for (n = 0; n < nbytes; n++)
1020		ibuf[n] ^= UCHAR(msgbuf, n);
1021	/*
1022	 * drop the bits
1023	 * we write chars until fewer than 7 bits,
1024	 * and then pad the last one with 0 bits
1025	 */
1026	for (n = 0; macbits > 7; n++, macbits -= 8)
1027		(void)putchar(CHAR(msgbuf, n));
1028	if (macbits > 0) {
1029		CHAR(msgbuf, 0) = 0x00;
1030		for (j = 0; j < macbits; j++)
1031			CHAR(msgbuf, 0) |= (CHAR(msgbuf, n)&bits[j]);
1032		(void)putchar(CHAR(msgbuf, 0));
1033	}
1034}
1035
1036#ifndef FASTWAY
1037/*
1038 * change from 8 bits/Uchar to 1 bit/Uchar
1039 */
1040static void
1041expand(Desbuf from, char *to)
1042{
1043	register int i, j;		/* counters in for loop */
1044
1045	for (i = 0; i < 8; i++)
1046		for (j = 0; j < 8; j++)
1047			*to++ = (CHAR(from, i)>>(7-j))&01;
1048}
1049
1050/*
1051 * change from 1 bit/char to 8 bits/Uchar
1052 */
1053static void
1054compress(char *from, Desbuf to)
1055{
1056	register int i, j;		/* counters in for loop */
1057
1058	for (i = 0; i < 8; i++) {
1059	 	CHAR(to, i) = 0;
1060		for (j = 0; j < 8; j++)
1061			CHAR(to, i) = ((*from++)<<(7-j))|CHAR(to, i);
1062	}
1063}
1064#endif
1065
1066/*
1067 * message about usage
1068 */
1069static void
1070usage(void)
1071{
1072
1073	(void) fprintf(stderr, "usage: %s %s\n", getprogname(),
1074	    "[-abdp] [-F bit] [-f bit] [-k key] [-m bit] [-o bit] [-v vector]");
1075	exit(1);
1076}
1077