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