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