xref: /minix/usr.bin/bdes/bdes.c (revision 84d9c625)
1 /*	$NetBSD: bdes.c,v 1.9 2013/08/15 20:48:56 joerg 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
47 static char sccsid[] = "@(#)bdes.c	8.1 (Berkeley) 6/6/93";
48 #else
49 __RCSID("$NetBSD: bdes.c,v 1.9 2013/08/15 20:48:56 joerg 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  */
133 typedef 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 */
144 static int keybase = KEY_DEFAULT;	/* how to interpret the key */
145 
146 static enum { 				/* encrypt, decrypt, authenticate */
147 	MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
148 } mode = MODE_ENCRYPT;
149 static enum {				/* ecb, cbc, cfb, cfba, ofb? */
150 	ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
151 } alg = ALG_CBC;
152 
153 static Desbuf ivec;				/* initialization vector */
154 static const char bits[] = {				/* used to extract bits from a char */
155 	'\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
156 };
157 static int inverse;				/* 0 to encrypt, 1 to decrypt */
158 static int macbits = -1;			/* number of bits in authentication */
159 static int fbbits = -1;			/* number of feedback bits */
160 static int pflag;				/* 1 to preserve parity bits */
161 
162 static int	setbits(char *, int);
163 static void	bdes_err(int, const char *) __dead;
164 static int	tobinhex(char, int);
165 static void	cvtkey(char *, char *);
166 static void	makekey(Desbuf);
167 static void	ecbenc(void);
168 static void	ecbdec(void);
169 static void	cbcenc(void);
170 static void	cbcdec(void);
171 static void	cbcauth(void);
172 static void	cfbenc(void);
173 static void	cfbdec(void);
174 static void	cfbaenc(void);
175 static void	cfbadec(void);
176 static void	ofbenc(void);
177 static void	ofbdec(void);
178 static void	cfbauth(void);
179 #ifndef FASTWAY
180 static void	expand(Desbuf, char *);
181 static void	compress(char *, Desbuf);
182 #endif
183 static void	usage(void) __dead;
184 
185 int
main(int ac,char * av[])186 main(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 encryptiooon 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  */
362 static void
bdes_err(int n,const char * s)363 bdes_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  */
376 static int
tobinhex(char c,int radix)377 tobinhex(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  */
406 static void
cvtkey(char * obuf,char * ibuf)407 cvtkey(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; ibuf[i] && i < 16; 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  */
473 static int
setbits(char * s,int mult)474 setbits(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  */
502 static void
makekey(Desbuf buf)503 makekey(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  */
530 static void
ecbenc(void)531 ecbenc(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  */
559 static void
ecbdec(void)560 ecbdec(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  */
592 static void
cbcenc(void)593 cbcenc(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  */
626 static void
cbcdec(void)627 cbcdec(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  */
664 static void
cbcauth(void)665 cbcauth(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  */
709 static void
cfbenc(void)710 cfbenc(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  */
751 static void
cfbdec(void)752 cfbdec(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  */
798 static void
cfbaenc(void)799 cfbaenc(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  */
844 static void
cfbadec(void)845 cfbadec(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  */
892 static void
ofbenc(void)893 ofbenc(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  */
938 static void
ofbdec(void)939 ofbdec(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  */
988 static void
cfbauth(void)989 cfbauth(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  */
1040 static void
expand(Desbuf from,char * to)1041 expand(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  */
1053 static void
compress(char * from,Desbuf to)1054 compress(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  */
1069 static void
usage(void)1070 usage(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