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