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