]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - secure/usr.bin/bdes/bdes.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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
41 #ifndef lint
42 static 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
49 static 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 */
122 int keybase = KEY_DEFAULT;              /* how to interpret the key */
123
124 enum {                                  /* encrypt, decrypt, authenticate */
125         MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
126 } mode = MODE_ENCRYPT;
127
128 enum {                                  /* ecb, cbc, cfb, cfba, ofb? */
129         ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
130 } alg = ALG_CBC;
131
132 DES_cblock ivec;                                /* initialization vector */
133
134 char bits[] = {                         /* used to extract bits from a char */
135         '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
136 };
137
138 int inverse;                            /* 0 to encrypt, 1 to decrypt */
139 int macbits = -1;                       /* number of bits in authentication */
140 int fbbits = -1;                        /* number of feedback bits */
141 int pflag;                              /* 1 to preserve parity bits */
142
143 DES_key_schedule schedule;              /* expanded DES key */
144
145 static void ecbenc(void);
146 static void ecbdec(void);
147 static void cbcenc(void);
148 static void cbcdec(void);
149 static void cfbenc(void);
150 static void cfbdec(void);
151 static void cfbaenc(void);
152 static void cfbadec(void);
153 static void ofbenc(void);
154 static void ofbdec(void);
155
156 static void cbcauth(void);
157 static void cfbauth(void);
158
159 static void cvtkey(DES_cblock, char *);
160 static int setbits(char *, int);
161 static void makekey(DES_cblock *);
162 static int tobinhex(char, int);
163
164 static void usage(void);
165
166 int
167 main(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  */
324 static int
325 tobinhex(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  */
354 static void
355 cvtkey(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  */
421 static int
422 setbits(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  */
462 static void
463 makekey(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  */
491 static void
492 ecbenc(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  */
520 static void
521 ecbdec(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  */
553 static void
554 cbcenc(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  */
587 static void
588 cbcdec(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  */
625 static void
626 cbcauth(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  */
670 static void
671 cfbenc(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  */
712 static void
713 cfbdec(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  */
759 static void
760 cfbaenc(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  */
804 static void
805 cfbadec(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  */
852 static void
853 ofbenc(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  */
898 static void
899 ofbdec(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  */
948 static void
949 cfbauth(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  */
999 static void
1000 usage(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 }