bdes(1): Sync with FreeBSD.
[dragonfly.git] / secure / usr.bin / bdes / bdes.c
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; ibuf[i] && i < 16; 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; ibuf[i] && i < 16; 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 }