2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Matt Bishop of Dartmouth College.
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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
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.3.2.1 2000/09/22 09:42:03 kris Exp $
43 * $DragonFly: src/secure/usr.bin/bdes/bdes.c,v 1.2 2003/06/17 04:27:48 dillon Exp $
47 * BDES -- DES encryption package for Berkeley Software Distribution 4.4
50 * -b use ECB (electronic code book) mode
51 * -d invert (decrypt) input
52 * -f b use b-bit CFB (cipher feedback) mode
53 * -F b use b-bit CFB (cipher feedback) alternative mode
54 * -k key use key as the cryptographic key
55 * -m b generate a MAC of length b
56 * -o b use b-bit OFB (output feedback) mode
57 * -p don't reset the parity bit
58 * -v v use v as the initialization vector (ignored for ECB)
59 * note: the last character of the last block is the integer indicating
60 * how many characters of that block are to be output
63 * Department of Mathematics and Computer Science
66 * Email: Matt.Bishop@dartmouth.edu
67 * ...!decvax!dartvax!Matt.Bishop
69 * See Technical Report PCS-TR91-158, Department of Mathematics and Computer
70 * Science, Dartmouth College, for a detailed description of the implemen-
71 * tation and differences between it and Sun's. The DES is described in
72 * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page
73 * or the technical report for a complete reference).
84 * BSD and System V systems offer special library calls that do
85 * block moves and fills, so if possible we take advantage of them
87 #define MEMCPY(dest,src,len) bcopy((src),(dest),(len))
88 #define MEMZERO(dest,len) bzero((dest),(len))
90 /* Hide the calls to the primitive encryption routines. */
93 #define DES_KEY(buf) \
94 if (des_setkey(buf)) \
96 #define DES_XFORM(buf) \
97 if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
100 #define DES_KEY(buf) { \
101 char bits1[64]; /* bits of key */ \
102 expand(buf, bits1); \
106 #define DES_XFORM(buf) { \
107 char bits1[64]; /* bits of message */ \
108 expand(buf, bits1); \
109 if (encrypt(bits1, inverse)) \
111 compress(bits1, buf); \
116 * this does an error-checking write
118 #define READ(buf, n) fread(buf, sizeof(char), n, stdin)
119 #define WRITE(buf,n) \
120 if (fwrite(buf, sizeof(char), n, stdout) != n) \
124 * some things to make references easier
126 typedef char Desbuf[8];
127 #define CHAR(x,i) (x[i])
128 #define UCHAR(x,i) (x[i])
129 #define BUFFER(x) (x)
130 #define UBUFFER(x) (x)
133 * global variables and related macros
135 #define KEY_DEFAULT 0 /* interpret radix of key from key */
136 #define KEY_ASCII 1 /* key is in ASCII characters */
137 int keybase = KEY_DEFAULT; /* how to interpret the key */
139 enum { /* encrypt, decrypt, authenticate */
140 MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
141 } mode = MODE_ENCRYPT;
142 enum { /* ecb, cbc, cfb, cfba, ofb? */
143 ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
146 Desbuf ivec; /* initialization vector */
147 char bits[] = { /* used to extract bits from a char */
148 '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
150 int inverse; /* 0 to encrypt, 1 to decrypt */
151 int macbits = -1; /* number of bits in authentication */
152 int fbbits = -1; /* number of feedback bits */
153 int pflag; /* 1 to preserve parity bits */
156 int ac; /* arg count */
157 char **av; /* arg vector */
159 extern int optind; /* option (argument) number */
160 extern char *optarg; /* argument to option if any */
161 register int i; /* counter in a for loop */
162 register char *p; /* used to obtain the key */
163 Desbuf msgbuf; /* I/O buffer */
164 int kflag; /* command-line encryptiooon key */
165 int argc; /* the real arg count */
166 char **argv; /* the real argument vector */
169 * Hide the arguments from ps(1) by making private copies of them
170 * and clobbering the global (visible to ps(1)) ones.
174 argv = malloc((argc + 1) * sizeof(char *));
175 for (i = 0; i < argc; ++i) {
176 argv[i] = strdup(av[i]);
177 MEMZERO(av[i], strlen(av[i]));
181 /* initialize the initialization vctor */
184 /* process the argument list */
186 while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != EOF)
188 case 'a': /* key is ASCII */
191 case 'b': /* use ECB mode */
194 case 'd': /* decrypt */
197 case 'F': /* use alternative CFB mode */
199 if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0)
200 err(-1, "-F: number must be 1-56 inclusive");
201 else if (fbbits == -1)
202 err(-1, "-F: number must be a multiple of 7");
204 case 'f': /* use CFB mode */
206 if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
207 err(-1, "-f: number must be 1-64 inclusive");
208 else if (fbbits == -1)
209 err(-1, "-f: number must be a multiple of 8");
211 case 'k': /* encryption key */
213 cvtkey(BUFFER(msgbuf), optarg);
215 case 'm': /* number of bits for MACing */
216 mode = MODE_AUTHENTICATE;
217 if ((macbits = setbits(optarg, 1)) > 64)
218 err(-1, "-m: number must be 0-64 inclusive");
220 case 'o': /* use OFB mode */
222 if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
223 err(-1, "-o: number must be 1-64 inclusive");
224 else if (fbbits == -1)
225 err(-1, "-o: number must be a multiple of 8");
227 case 'p': /* preserve parity bits */
230 case 'v': /* set initialization vector */
231 cvtkey(BUFFER(ivec), optarg);
239 * if the key's not ASCII, assume it is
245 p = getpass("Enter key: ");
247 * copy it, nul-padded, into the key area
249 cvtkey(BUFFER(msgbuf), p);
253 inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT;
258 case MODE_AUTHENTICATE: /* authenticate using CBC mode */
261 case MODE_DECRYPT: /* decrypt using CBC mode */
264 case MODE_ENCRYPT: /* encrypt using CBC mode */
271 case MODE_AUTHENTICATE: /* authenticate using CFB mode */
274 case MODE_DECRYPT: /* decrypt using CFB mode */
277 case MODE_ENCRYPT: /* encrypt using CFB mode */
284 case MODE_AUTHENTICATE: /* authenticate using CFBA mode */
285 err(-1, "can't authenticate with CFBA mode");
287 case MODE_DECRYPT: /* decrypt using CFBA mode */
290 case MODE_ENCRYPT: /* encrypt using CFBA mode */
297 case MODE_AUTHENTICATE: /* authenticate using ECB mode */
298 err(-1, "can't authenticate with ECB mode");
300 case MODE_DECRYPT: /* decrypt using ECB mode */
303 case MODE_ENCRYPT: /* encrypt using ECB mode */
310 case MODE_AUTHENTICATE: /* authenticate using OFB mode */
311 err(-1, "can't authenticate with OFB mode");
313 case MODE_DECRYPT: /* decrypt using OFB mode */
316 case MODE_ENCRYPT: /* encrypt using OFB mode */
326 * print a warning message and, possibly, terminate
329 int n; /* offending block number */
330 char *s; /* the message */
333 (void)fprintf(stderr, "bdes (block %d): ", n);
335 (void)fprintf(stderr, "bdes: ");
336 (void)fprintf(stderr, "%s\n", s ? s : strerror(errno));
341 * map a hex character to an integer
344 char c; /* char to be converted */
345 int radix; /* base (2 to 16) */
348 case '0': return(0x0);
349 case '1': return(0x1);
350 case '2': return(radix > 2 ? 0x2 : -1);
351 case '3': return(radix > 3 ? 0x3 : -1);
352 case '4': return(radix > 4 ? 0x4 : -1);
353 case '5': return(radix > 5 ? 0x5 : -1);
354 case '6': return(radix > 6 ? 0x6 : -1);
355 case '7': return(radix > 7 ? 0x7 : -1);
356 case '8': return(radix > 8 ? 0x8 : -1);
357 case '9': return(radix > 9 ? 0x9 : -1);
358 case 'A': case 'a': return(radix > 10 ? 0xa : -1);
359 case 'B': case 'b': return(radix > 11 ? 0xb : -1);
360 case 'C': case 'c': return(radix > 12 ? 0xc : -1);
361 case 'D': case 'd': return(radix > 13 ? 0xd : -1);
362 case 'E': case 'e': return(radix > 14 ? 0xe : -1);
363 case 'F': case 'f': return(radix > 15 ? 0xf : -1);
372 * convert the key to a bit pattern
375 char *obuf; /* bit pattern */
376 char *ibuf; /* the key itself */
378 register int i, j; /* counter in a for loop */
379 int nbuf[64]; /* used for hex/key translation */
382 * just switch on the key base
385 case KEY_ASCII: /* ascii to integer */
386 (void)strncpy(obuf, ibuf, 8);
388 case KEY_DEFAULT: /* tell from context */
390 * leading '0x' or '0X' == hex key
392 if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) {
395 * now translate it, bombing on any illegal hex digit
397 for (i = 0; ibuf[i] && i < 16; i++)
398 if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1)
399 err(-1, "bad hex digit in key");
402 for (i = 0; i < 8; i++)
404 ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
405 /* preserve parity bits */
410 * leading '0b' or '0B' == binary key
412 if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) {
415 * now translate it, bombing on any illegal binary digit
417 for (i = 0; ibuf[i] && i < 16; i++)
418 if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1)
419 err(-1, "bad binary digit in key");
422 for (i = 0; i < 8; i++)
423 for (j = 0; j < 8; j++)
424 obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
425 /* preserve parity bits */
430 * no special leader -- ASCII
432 (void)strncpy(obuf, ibuf, 8);
437 * convert an ASCII string into a decimal number:
438 * 1. must be between 0 and 64 inclusive
439 * 2. must be a valid decimal number
440 * 3. must be a multiple of mult
443 char *s; /* the ASCII string */
444 int mult; /* what it must be a multiple of */
446 register char *p; /* pointer in a for loop */
447 register int n = 0; /* the integer collected */
457 for (p = s; *p; p++) {
459 n = n * 10 + *p - '0';
461 err(-1, "bad decimal digit in MAC length");
465 * be sure it's a multiple of mult
467 return((n % mult != 0) ? -1 : n);
474 * This sets the DES key and (if you're using the deszip version)
475 * the direction of the transformation. This uses the Sun
476 * to map the 64-bit key onto the 56 bits that the key schedule
477 * generation routines use: the old way, which just uses the user-
478 * supplied 64 bits as is, and the new way, which resets the parity
479 * bit to be the same as the low-order bit in each character. The
480 * new way generates a greater variety of key schedules, since many
481 * systems set the parity (high) bit of each character to 0, and the
482 * DES ignores the low order bit of each character.
485 Desbuf buf; /* key block */
487 register int i, j; /* counter in a for loop */
488 register int par; /* parity counter */
491 * if the parity is not preserved, flip it
494 for (i = 0; i < 8; i++) {
496 for (j = 1; j < 8; j++)
497 if ((bits[j]&UCHAR(buf, i)) != 0)
500 UCHAR(buf, i) = UCHAR(buf, i)&0177;
502 UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
506 DES_KEY(UBUFFER(buf));
510 * This encrypts using the Electronic Code Book mode of DES
514 register int n; /* number of bytes actually read */
515 register int bn; /* block number */
516 Desbuf msgbuf; /* I/O buffer */
518 for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
520 * do the transformation
522 DES_XFORM(UBUFFER(msgbuf));
523 WRITE(BUFFER(msgbuf), 8);
526 * at EOF or last block -- in either case, the last byte contains
527 * the character representation of the number of bytes in it
530 MEMZERO(&CHAR(msgbuf, n), 8 - n);
532 DES_XFORM(UBUFFER(msgbuf));
533 WRITE(BUFFER(msgbuf), 8);
538 * This decrypts using the Electronic Code Book mode of DES
542 register int n; /* number of bytes actually read */
543 register int c; /* used to test for EOF */
544 register int bn; /* block number */
545 Desbuf msgbuf; /* I/O buffer */
547 for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
549 * do the transformation
551 DES_XFORM(UBUFFER(msgbuf));
553 * if the last one, handle it specially
555 if ((c = getchar()) == EOF) {
558 err(bn, "decryption failed (block corrupted)");
561 (void)ungetc(c, stdin);
562 WRITE(BUFFER(msgbuf), n);
565 err(bn, "decryption failed (incomplete block)");
569 * This encrypts using the Cipher Block Chaining mode of DES
573 register int n; /* number of bytes actually read */
574 register int bn; /* block number */
575 Desbuf msgbuf; /* I/O buffer */
578 * do the transformation
580 for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
581 for (n = 0; n < 8; n++)
582 CHAR(msgbuf, n) ^= CHAR(ivec, n);
583 DES_XFORM(UBUFFER(msgbuf));
584 MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
585 WRITE(BUFFER(msgbuf), 8);
588 * at EOF or last block -- in either case, the last byte contains
589 * the character representation of the number of bytes in it
592 MEMZERO(&CHAR(msgbuf, n), 8 - n);
594 for (n = 0; n < 8; n++)
595 CHAR(msgbuf, n) ^= CHAR(ivec, n);
596 DES_XFORM(UBUFFER(msgbuf));
597 WRITE(BUFFER(msgbuf), 8);
602 * This decrypts using the Cipher Block Chaining mode of DES
606 register int n; /* number of bytes actually read */
607 Desbuf msgbuf; /* I/O buffer */
608 Desbuf ibuf; /* temp buffer for initialization vector */
609 register int c; /* used to test for EOF */
610 register int bn; /* block number */
612 for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
614 * do the transformation
616 MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8);
617 DES_XFORM(UBUFFER(msgbuf));
618 for (c = 0; c < 8; c++)
619 UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
620 MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8);
622 * if the last one, handle it specially
624 if ((c = getchar()) == EOF) {
627 err(bn, "decryption failed (block corrupted)");
630 (void)ungetc(c, stdin);
631 WRITE(BUFFER(msgbuf), n);
634 err(bn, "decryption failed (incomplete block)");
638 * This authenticates using the Cipher Block Chaining mode of DES
642 register int n, j; /* number of bytes actually read */
643 Desbuf msgbuf; /* I/O buffer */
644 Desbuf encbuf; /* encryption buffer */
647 * do the transformation
648 * note we DISCARD the encrypted block;
649 * we only care about the last one
651 while ((n = READ(BUFFER(msgbuf), 8)) == 8) {
652 for (n = 0; n < 8; n++)
653 CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
654 DES_XFORM(UBUFFER(encbuf));
655 MEMCPY(BUFFER(ivec), BUFFER(encbuf), 8);
658 * now compute the last one, right padding with '\0' if need be
661 MEMZERO(&CHAR(msgbuf, n), 8 - n);
662 for (n = 0; n < 8; n++)
663 CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
664 DES_XFORM(UBUFFER(encbuf));
668 * we write chars until fewer than 7 bits,
669 * and then pad the last one with 0 bits
671 for (n = 0; macbits > 7; n++, macbits -= 8)
672 (void)putchar(CHAR(encbuf, n));
674 CHAR(msgbuf, 0) = 0x00;
675 for (j = 0; j < macbits; j++)
676 CHAR(msgbuf, 0) |= (CHAR(encbuf, n)&bits[j]);
677 (void)putchar(CHAR(msgbuf, 0));
682 * This encrypts using the Cipher FeedBack mode of DES
686 register int n; /* number of bytes actually read */
687 register int nbytes; /* number of bytes to read */
688 register int bn; /* block number */
689 char ibuf[8]; /* input buffer */
690 Desbuf msgbuf; /* encryption buffer */
693 * do things in bytes, not bits
697 * do the transformation
699 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
700 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
701 DES_XFORM(UBUFFER(msgbuf));
702 for (n = 0; n < 8 - nbytes; n++)
703 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
704 for (n = 0; n < nbytes; n++)
705 UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
706 WRITE(&CHAR(ivec, 8-nbytes), nbytes);
709 * at EOF or last block -- in either case, the last byte contains
710 * the character representation of the number of bytes in it
713 MEMZERO(&ibuf[n], nbytes - n);
714 ibuf[nbytes - 1] = n;
715 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
716 DES_XFORM(UBUFFER(msgbuf));
717 for (n = 0; n < nbytes; n++)
718 ibuf[n] ^= UCHAR(msgbuf, n);
723 * This decrypts using the Cipher Block Chaining mode of DES
727 register int n; /* number of bytes actually read */
728 register int c; /* used to test for EOF */
729 register int nbytes; /* number of bytes to read */
730 register int bn; /* block number */
731 char ibuf[8]; /* input buffer */
732 char obuf[8]; /* output buffer */
733 Desbuf msgbuf; /* encryption buffer */
736 * do things in bytes, not bits
740 * do the transformation
742 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
743 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
744 DES_XFORM(UBUFFER(msgbuf));
745 for (c = 0; c < 8 - nbytes; c++)
746 CHAR(ivec, c) = CHAR(ivec, c+nbytes);
747 for (c = 0; c < nbytes; c++) {
748 CHAR(ivec, 8-nbytes+c) = ibuf[c];
749 obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
752 * if the last one, handle it specially
754 if ((c = getchar()) == EOF) {
756 if (n < 0 || n > nbytes-1)
757 err(bn, "decryption failed (block corrupted)");
760 (void)ungetc(c, stdin);
764 err(bn, "decryption failed (incomplete block)");
768 * This encrypts using the alternative Cipher FeedBack mode of DES
772 register int n; /* number of bytes actually read */
773 register int nbytes; /* number of bytes to read */
774 register int bn; /* block number */
775 char ibuf[8]; /* input buffer */
776 char obuf[8]; /* output buffer */
777 Desbuf msgbuf; /* encryption buffer */
780 * do things in bytes, not bits
784 * do the transformation
786 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
787 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
788 DES_XFORM(UBUFFER(msgbuf));
789 for (n = 0; n < 8 - nbytes; n++)
790 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
791 for (n = 0; n < nbytes; n++)
792 UCHAR(ivec, 8-nbytes+n) = (ibuf[n] ^ UCHAR(msgbuf, n))
794 for (n = 0; n < nbytes; n++)
795 obuf[n] = CHAR(ivec, 8-nbytes+n)&0177;
799 * at EOF or last block -- in either case, the last byte contains
800 * the character representation of the number of bytes in it
803 MEMZERO(&ibuf[n], nbytes - n);
804 ibuf[nbytes - 1] = ('0' + n)|0200;
805 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
806 DES_XFORM(UBUFFER(msgbuf));
807 for (n = 0; n < nbytes; n++)
808 ibuf[n] ^= UCHAR(msgbuf, n);
813 * This decrypts using the alternative Cipher Block Chaining mode of DES
817 register int n; /* number of bytes actually read */
818 register int c; /* used to test for EOF */
819 register int nbytes; /* number of bytes to read */
820 register int bn; /* block number */
821 char ibuf[8]; /* input buffer */
822 char obuf[8]; /* output buffer */
823 Desbuf msgbuf; /* encryption buffer */
826 * do things in bytes, not bits
830 * do the transformation
832 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
833 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
834 DES_XFORM(UBUFFER(msgbuf));
835 for (c = 0; c < 8 - nbytes; c++)
836 CHAR(ivec, c) = CHAR(ivec, c+nbytes);
837 for (c = 0; c < nbytes; c++) {
838 CHAR(ivec, 8-nbytes+c) = ibuf[c]|0200;
839 obuf[c] = (ibuf[c] ^ UCHAR(msgbuf, c))&0177;
842 * if the last one, handle it specially
844 if ((c = getchar()) == EOF) {
845 if ((n = (obuf[nbytes-1] - '0')) < 0
847 err(bn, "decryption failed (block corrupted)");
850 (void)ungetc(c, stdin);
854 err(bn, "decryption failed (incomplete block)");
859 * This encrypts using the Output FeedBack mode of DES
863 register int n; /* number of bytes actually read */
864 register int c; /* used to test for EOF */
865 register int nbytes; /* number of bytes to read */
866 register int bn; /* block number */
867 char ibuf[8]; /* input buffer */
868 char obuf[8]; /* output buffer */
869 Desbuf msgbuf; /* encryption buffer */
872 * do things in bytes, not bits
876 * do the transformation
878 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
879 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
880 DES_XFORM(UBUFFER(msgbuf));
881 for (n = 0; n < 8 - nbytes; n++)
882 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
883 for (n = 0; n < nbytes; n++) {
884 UCHAR(ivec, 8-nbytes+n) = UCHAR(msgbuf, n);
885 obuf[n] = ibuf[n] ^ UCHAR(msgbuf, n);
890 * at EOF or last block -- in either case, the last byte contains
891 * the character representation of the number of bytes in it
894 MEMZERO(&ibuf[n], nbytes - n);
895 ibuf[nbytes - 1] = n;
896 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
897 DES_XFORM(UBUFFER(msgbuf));
898 for (c = 0; c < nbytes; c++)
899 ibuf[c] ^= UCHAR(msgbuf, c);
904 * This decrypts using the Output Block Chaining mode of DES
908 register int n; /* number of bytes actually read */
909 register int c; /* used to test for EOF */
910 register int nbytes; /* number of bytes to read */
911 register int bn; /* block number */
912 char ibuf[8]; /* input buffer */
913 char obuf[8]; /* output buffer */
914 Desbuf msgbuf; /* encryption buffer */
917 * do things in bytes, not bits
921 * do the transformation
923 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
924 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
925 DES_XFORM(UBUFFER(msgbuf));
926 for (c = 0; c < 8 - nbytes; c++)
927 CHAR(ivec, c) = CHAR(ivec, c+nbytes);
928 for (c = 0; c < nbytes; c++) {
929 CHAR(ivec, 8-nbytes+c) = UCHAR(msgbuf, c);
930 obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
933 * if the last one, handle it specially
935 if ((c = getchar()) == EOF) {
937 if (n < 0 || n > nbytes-1)
938 err(bn, "decryption failed (block corrupted)");
941 (void)ungetc(c, stdin);
948 err(bn, "decryption failed (incomplete block)");
952 * This authenticates using the Cipher FeedBack mode of DES
956 register int n, j; /* number of bytes actually read */
957 register int nbytes; /* number of bytes to read */
958 char ibuf[8]; /* input buffer */
959 Desbuf msgbuf; /* encryption buffer */
962 * do things in bytes, not bits
966 * do the transformation
968 while ((n = READ(ibuf, nbytes)) == nbytes) {
969 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
970 DES_XFORM(UBUFFER(msgbuf));
971 for (n = 0; n < 8 - nbytes; n++)
972 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
973 for (n = 0; n < nbytes; n++)
974 UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
977 * at EOF or last block -- in either case, the last byte contains
978 * the character representation of the number of bytes in it
980 MEMZERO(&ibuf[n], nbytes - n);
981 ibuf[nbytes - 1] = '0' + n;
982 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
983 DES_XFORM(UBUFFER(msgbuf));
984 for (n = 0; n < nbytes; n++)
985 ibuf[n] ^= UCHAR(msgbuf, n);
988 * we write chars until fewer than 7 bits,
989 * and then pad the last one with 0 bits
991 for (n = 0; macbits > 7; n++, macbits -= 8)
992 (void)putchar(CHAR(msgbuf, n));
994 CHAR(msgbuf, 0) = 0x00;
995 for (j = 0; j < macbits; j++)
996 CHAR(msgbuf, 0) |= (CHAR(msgbuf, n)&bits[j]);
997 (void)putchar(CHAR(msgbuf, 0));
1003 * change from 8 bits/Uchar to 1 bit/Uchar
1006 Desbuf from; /* 8bit/unsigned char string */
1007 char *to; /* 1bit/char string */
1009 register int i, j; /* counters in for loop */
1011 for (i = 0; i < 8; i++)
1012 for (j = 0; j < 8; j++)
1013 *to++ = (CHAR(from, i)>>(7-j))&01;
1017 * change from 1 bit/char to 8 bits/Uchar
1020 char *from; /* 1bit/char string */
1021 Desbuf to; /* 8bit/unsigned char string */
1023 register int i, j; /* counters in for loop */
1025 for (i = 0; i < 8; i++) {
1027 for (j = 0; j < 8; j++)
1028 CHAR(to, i) = ((*from++)<<(7-j))|CHAR(to, i);
1034 * message about usage
1038 (void)fprintf(stderr, "%s\n",
1039 "usage: bdes [-abdp] [-F bit] [-f bit] [-k key] [-m bit] [-o bit] [-v vector]");