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