Sync with manuals from netbsd-8 branch.
[minix3.git] / usr.bin / bdes / bdes.c
blobb481b61dd6e385ba9abbd8018fbdd2e87ad3dcec
1 /* $NetBSD: bdes.c,v 1.9 2013/08/15 20:48:56 joerg Exp $ */
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Matt Bishop of Dartmouth College.
10 * The United States Government has rights in this work pursuant
11 * to contract no. NAG 2-680 between the National Aeronautics and
12 * Space Administration and Dartmouth College.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #include <sys/cdefs.h>
40 #ifndef lint
41 __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
42 The Regents of the University of California. All rights reserved.");
43 #endif /* not lint */
45 #ifndef lint
46 #if 0
47 static char sccsid[] = "@(#)bdes.c 8.1 (Berkeley) 6/6/93";
48 #else
49 __RCSID("$NetBSD: bdes.c,v 1.9 2013/08/15 20:48:56 joerg Exp $");
50 #endif
51 #endif /* not lint */
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
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
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).
83 #include <errno.h>
84 #include <unistd.h>
85 #include <stdio.h>
86 #include <ctype.h>
87 #include <stdlib.h>
88 #include <string.h>
91 * BSD and System V systems offer special library calls that do
92 * block moves and fills, so if possible we take advantage of them
94 #define MEMCPY(dest,src,len) bcopy((src),(dest),(len))
95 #define MEMZERO(dest,len) bzero((dest),(len))
97 /* Hide the calls to the primitive encryption routines. */
98 #define FASTWAY
99 #ifdef FASTWAY
100 #define DES_KEY(buf) \
101 if (des_setkey(buf)) \
102 bdes_err(0, "des_setkey");
103 #define DES_XFORM(buf) \
104 if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
105 bdes_err(0, "des_cipher");
106 #else
107 #define DES_KEY(buf) { \
108 char bits1[64]; /* bits of key */ \
109 expand(buf, bits1); \
110 if (setkey(bits1)) \
111 bdes_err(0, "setkey"); \
113 #define DES_XFORM(buf) { \
114 char bits1[64]; /* bits of message */ \
115 expand(buf, bits1); \
116 if (encrypt(bits1, inverse)) \
117 bdes_err(0, "encrypt"); \
118 compress(bits1, buf); \
120 #endif
123 * this does an error-checking write
125 #define READ(buf, n) fread(buf, sizeof(char), n, stdin)
126 #define WRITE(buf,n) \
127 if (fwrite(buf, sizeof(char), n, stdout) != (size_t)n) \
128 bdes_err(bn, NULL);
131 * some things to make references easier
133 typedef char Desbuf[8];
134 #define CHAR(x,i) (x[i])
135 #define UCHAR(x,i) (x[i])
136 #define BUFFER(x) (x)
137 #define UBUFFER(x) (x)
140 * global variables and related macros
142 #define KEY_DEFAULT 0 /* interpret radix of key from key */
143 #define KEY_ASCII 1 /* key is in ASCII characters */
144 static int keybase = KEY_DEFAULT; /* how to interpret the key */
146 static enum { /* encrypt, decrypt, authenticate */
147 MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
148 } mode = MODE_ENCRYPT;
149 static enum { /* ecb, cbc, cfb, cfba, ofb? */
150 ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
151 } alg = ALG_CBC;
153 static Desbuf ivec; /* initialization vector */
154 static const char bits[] = { /* used to extract bits from a char */
155 '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
157 static int inverse; /* 0 to encrypt, 1 to decrypt */
158 static int macbits = -1; /* number of bits in authentication */
159 static int fbbits = -1; /* number of feedback bits */
160 static int pflag; /* 1 to preserve parity bits */
162 static int setbits(char *, int);
163 static void bdes_err(int, const char *) __dead;
164 static int tobinhex(char, int);
165 static void cvtkey(char *, char *);
166 static void makekey(Desbuf);
167 static void ecbenc(void);
168 static void ecbdec(void);
169 static void cbcenc(void);
170 static void cbcdec(void);
171 static void cbcauth(void);
172 static void cfbenc(void);
173 static void cfbdec(void);
174 static void cfbaenc(void);
175 static void cfbadec(void);
176 static void ofbenc(void);
177 static void ofbdec(void);
178 static void cfbauth(void);
179 #ifndef FASTWAY
180 static void expand(Desbuf, char *);
181 static void compress(char *, Desbuf);
182 #endif
183 static void usage(void) __dead;
186 main(int ac, char *av[])
188 register int i; /* counter in a for loop */
189 register char *p; /* used to obtain the key */
190 Desbuf msgbuf; /* I/O buffer */
191 int kflag; /* command-line encryptiooon key */
192 int argc; /* the real arg count */
193 char **argv; /* the real argument vector */
196 * Hide the arguments from ps(1) by making private copies of them
197 * and clobbering the global (visible to ps(1)) ones.
199 argc = ac;
200 ac = 1;
201 argv = malloc((argc + 1) * sizeof(char *));
202 for (i = 0; i < argc; ++i) {
203 argv[i] = strdup(av[i]);
204 MEMZERO(av[i], strlen(av[i]));
206 argv[argc] = NULL;
208 /* initialize the initialization vctor */
209 MEMZERO(ivec, 8);
211 /* process the argument list */
212 kflag = 0;
213 while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1)
214 switch(i) {
215 case 'a': /* key is ASCII */
216 keybase = KEY_ASCII;
217 break;
218 case 'b': /* use ECB mode */
219 alg = ALG_ECB;
220 break;
221 case 'd': /* decrypt */
222 mode = MODE_DECRYPT;
223 break;
224 case 'F': /* use alternative CFB mode */
225 alg = ALG_CFBA;
226 if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0)
227 bdes_err(-1,
228 "-F: number must be 1-56 inclusive");
229 else if (fbbits == -1)
230 bdes_err(-1,
231 "-F: number must be a multiple of 7");
232 break;
233 case 'f': /* use CFB mode */
234 alg = ALG_CFB;
235 if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
236 bdes_err(-1,
237 "-f: number must be 1-64 inclusive");
238 else if (fbbits == -1)
239 bdes_err(-1,
240 "-f: number must be a multiple of 8");
241 break;
242 case 'k': /* encryption key */
243 kflag = 1;
244 cvtkey(BUFFER(msgbuf), optarg);
245 break;
246 case 'm': /* number of bits for MACing */
247 mode = MODE_AUTHENTICATE;
248 if ((macbits = setbits(optarg, 1)) > 64)
249 bdes_err(-1,
250 "-m: number must be 0-64 inclusive");
251 break;
252 case 'o': /* use OFB mode */
253 alg = ALG_OFB;
254 if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
255 bdes_err(-1,
256 "-o: number must be 1-64 inclusive");
257 else if (fbbits == -1)
258 bdes_err(-1,
259 "-o: number must be a multiple of 8");
260 break;
261 case 'p': /* preserve parity bits */
262 pflag = 1;
263 break;
264 case 'v': /* set initialization vector */
265 cvtkey(BUFFER(ivec), optarg);
266 break;
267 default: /* error */
268 usage();
271 if (!kflag) {
273 * if the key's not ASCII, assume it is
275 keybase = KEY_ASCII;
277 * get the key
279 p = getpass("Enter key: ");
281 * copy it, nul-padded, into the key area
283 cvtkey(BUFFER(msgbuf), p);
286 makekey(msgbuf);
287 inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT;
289 switch(alg) {
290 case ALG_CBC:
291 switch(mode) {
292 case MODE_AUTHENTICATE: /* authenticate using CBC mode */
293 cbcauth();
294 break;
295 case MODE_DECRYPT: /* decrypt using CBC mode */
296 cbcdec();
297 break;
298 case MODE_ENCRYPT: /* encrypt using CBC mode */
299 cbcenc();
300 break;
302 break;
303 case ALG_CFB:
304 switch(mode) {
305 case MODE_AUTHENTICATE: /* authenticate using CFB mode */
306 cfbauth();
307 break;
308 case MODE_DECRYPT: /* decrypt using CFB mode */
309 cfbdec();
310 break;
311 case MODE_ENCRYPT: /* encrypt using CFB mode */
312 cfbenc();
313 break;
315 break;
316 case ALG_CFBA:
317 switch(mode) {
318 case MODE_AUTHENTICATE: /* authenticate using CFBA mode */
319 bdes_err(-1, "can't authenticate with CFBA mode");
320 break;
321 case MODE_DECRYPT: /* decrypt using CFBA mode */
322 cfbadec();
323 break;
324 case MODE_ENCRYPT: /* encrypt using CFBA mode */
325 cfbaenc();
326 break;
328 break;
329 case ALG_ECB:
330 switch(mode) {
331 case MODE_AUTHENTICATE: /* authenticate using ECB mode */
332 bdes_err(-1, "can't authenticate with ECB mode");
333 break;
334 case MODE_DECRYPT: /* decrypt using ECB mode */
335 ecbdec();
336 break;
337 case MODE_ENCRYPT: /* encrypt using ECB mode */
338 ecbenc();
339 break;
341 break;
342 case ALG_OFB:
343 switch(mode) {
344 case MODE_AUTHENTICATE: /* authenticate using OFB mode */
345 bdes_err(-1, "can't authenticate with OFB mode");
346 break;
347 case MODE_DECRYPT: /* decrypt using OFB mode */
348 ofbdec();
349 break;
350 case MODE_ENCRYPT: /* encrypt using OFB mode */
351 ofbenc();
352 break;
354 break;
356 exit(0);
360 * print a warning message and, possibly, terminate
362 static void
363 bdes_err(int n, const char *s)
365 if (n > 0)
366 (void)fprintf(stderr, "bdes (block %d): ", n);
367 else
368 (void)fprintf(stderr, "bdes: ");
369 (void)fprintf(stderr, "%s\n", s ? s : strerror(errno));
370 exit(1);
374 * map a hex character to an integer
376 static int
377 tobinhex(char c, int radix)
379 switch(c) {
380 case '0': return(0x0);
381 case '1': return(0x1);
382 case '2': return(radix > 2 ? 0x2 : -1);
383 case '3': return(radix > 3 ? 0x3 : -1);
384 case '4': return(radix > 4 ? 0x4 : -1);
385 case '5': return(radix > 5 ? 0x5 : -1);
386 case '6': return(radix > 6 ? 0x6 : -1);
387 case '7': return(radix > 7 ? 0x7 : -1);
388 case '8': return(radix > 8 ? 0x8 : -1);
389 case '9': return(radix > 9 ? 0x9 : -1);
390 case 'A': case 'a': return(radix > 10 ? 0xa : -1);
391 case 'B': case 'b': return(radix > 11 ? 0xb : -1);
392 case 'C': case 'c': return(radix > 12 ? 0xc : -1);
393 case 'D': case 'd': return(radix > 13 ? 0xd : -1);
394 case 'E': case 'e': return(radix > 14 ? 0xe : -1);
395 case 'F': case 'f': return(radix > 15 ? 0xf : -1);
398 * invalid character
400 return(-1);
404 * convert the key to a bit pattern
406 static void
407 cvtkey(char *obuf, char *ibuf)
409 register int i, j; /* counter in a for loop */
410 int nbuf[64]; /* used for hex/key translation */
413 * just switch on the key base
415 switch(keybase) {
416 case KEY_ASCII: /* ascii to integer */
417 (void)strncpy(obuf, ibuf, 8);
418 return;
419 case KEY_DEFAULT: /* tell from context */
421 * leading '0x' or '0X' == hex key
423 if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) {
424 ibuf = &ibuf[2];
426 * now translate it, bombing on any illegal hex digit
428 for (i = 0; ibuf[i] && i < 16; i++)
429 if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1)
430 bdes_err(-1, "bad hex digit in key");
431 while (i < 16)
432 nbuf[i++] = 0;
433 for (i = 0; i < 8; i++)
434 obuf[i] =
435 ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
436 /* preserve parity bits */
437 pflag = 1;
438 return;
441 * leading '0b' or '0B' == binary key
443 if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) {
444 ibuf = &ibuf[2];
446 * now translate it, bombing on any illegal binary digit
448 for (i = 0; ibuf[i] && i < 16; i++)
449 if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1)
450 bdes_err(-1, "bad binary digit in key");
451 while (i < 64)
452 nbuf[i++] = 0;
453 for (i = 0; i < 8; i++)
454 for (j = 0; j < 8; j++)
455 obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
456 /* preserve parity bits */
457 pflag = 1;
458 return;
461 * no special leader -- ASCII
463 (void)strncpy(obuf, ibuf, 8);
468 * convert an ASCII string into a decimal number:
469 * 1. must be between 0 and 64 inclusive (or 56, checked by caller)
470 * 2. must be a valid decimal number
471 * 3. must be a multiple of mult
473 static int
474 setbits(char *s, int mult)
476 char *p;
477 int n; /* the integer collected */
479 n = strtoul(s, &p, 10);
480 if (*p != 0)
481 bdes_err(-1, "bad decimal digit in MAC length");
483 * be sure it's a multiple of mult
485 return((n % mult != 0) ? -1 : n);
488 /*****************
489 * DES FUNCTIONS *
490 *****************/
492 * This sets the DES key and (if you're using the deszip version)
493 * the direction of the transformation. This uses the Sun
494 * to map the 64-bit key onto the 56 bits that the key schedule
495 * generation routines use: the old way, which just uses the user-
496 * supplied 64 bits as is, and the new way, which resets the parity
497 * bit to be the same as the low-order bit in each character. The
498 * new way generates a greater variety of key schedules, since many
499 * systems set the parity (high) bit of each character to 0, and the
500 * DES ignores the low order bit of each character.
502 static void
503 makekey(Desbuf buf)
505 register int i, j; /* counter in a for loop */
506 register int par; /* parity counter */
509 * if the parity is not preserved, flip it
511 if (!pflag) {
512 for (i = 0; i < 8; i++) {
513 par = 0;
514 for (j = 1; j < 8; j++)
515 if ((bits[j]&UCHAR(buf, i)) != 0)
516 par++;
517 if ((par&01) == 01)
518 UCHAR(buf, i) = UCHAR(buf, i)&0177;
519 else
520 UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
524 DES_KEY(UBUFFER(buf));
528 * This encrypts using the Electronic Code Book mode of DES
530 static void
531 ecbenc(void)
533 register int n; /* number of bytes actually read */
534 register int bn; /* block number */
535 Desbuf msgbuf; /* I/O buffer */
537 for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
539 * do the transformation
541 DES_XFORM(UBUFFER(msgbuf));
542 WRITE(BUFFER(msgbuf), 8);
545 * at EOF or last block -- in either ase, the last byte contains
546 * the character representation of the number of bytes in it
548 bn++;
549 MEMZERO(&CHAR(msgbuf, n), 8 - n);
550 CHAR(msgbuf, 7) = n;
551 DES_XFORM(UBUFFER(msgbuf));
552 WRITE(BUFFER(msgbuf), 8);
557 * This decrypts using the Electronic Code Book mode of DES
559 static void
560 ecbdec(void)
562 register int n; /* number of bytes actually read */
563 register int c; /* used to test for EOF */
564 register int bn; /* block number */
565 Desbuf msgbuf; /* I/O buffer */
567 for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
569 * do the transformation
571 DES_XFORM(UBUFFER(msgbuf));
573 * if the last one, handle it specially
575 if ((c = getchar()) == EOF) {
576 n = CHAR(msgbuf, 7);
577 if (n < 0 || n > 7)
578 bdes_err(bn,
579 "decryption failed (block corrupted)");
581 else
582 (void)ungetc(c, stdin);
583 WRITE(BUFFER(msgbuf), n);
585 if (n > 0)
586 bdes_err(bn, "decryption failed (incomplete block)");
590 * This encrypts using the Cipher Block Chaining mode of DES
592 static void
593 cbcenc(void)
595 register int n; /* number of bytes actually read */
596 register int bn; /* block number */
597 Desbuf msgbuf; /* I/O buffer */
600 * do the transformation
602 for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
603 for (n = 0; n < 8; n++)
604 CHAR(msgbuf, n) ^= CHAR(ivec, n);
605 DES_XFORM(UBUFFER(msgbuf));
606 MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
607 WRITE(BUFFER(msgbuf), 8);
610 * at EOF or last block -- in either case, the last byte contains
611 * the character representation of the number of bytes in it
613 bn++;
614 MEMZERO(&CHAR(msgbuf, n), 8 - n);
615 CHAR(msgbuf, 7) = n;
616 for (n = 0; n < 8; n++)
617 CHAR(msgbuf, n) ^= CHAR(ivec, n);
618 DES_XFORM(UBUFFER(msgbuf));
619 WRITE(BUFFER(msgbuf), 8);
624 * This decrypts using the Cipher Block Chaining mode of DES
626 static void
627 cbcdec(void)
629 register int n; /* number of bytes actually read */
630 Desbuf msgbuf; /* I/O buffer */
631 Desbuf ibuf; /* temp buffer for initialization vector */
632 register int c; /* used to test for EOF */
633 register int bn; /* block number */
635 for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
637 * do the transformation
639 MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8);
640 DES_XFORM(UBUFFER(msgbuf));
641 for (c = 0; c < 8; c++)
642 UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
643 MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8);
645 * if the last one, handle it specially
647 if ((c = getchar()) == EOF) {
648 n = CHAR(msgbuf, 7);
649 if (n < 0 || n > 7)
650 bdes_err(bn,
651 "decryption failed (block corrupted)");
653 else
654 (void)ungetc(c, stdin);
655 WRITE(BUFFER(msgbuf), n);
657 if (n > 0)
658 bdes_err(bn, "decryption failed (incomplete block)");
662 * This authenticates using the Cipher Block Chaining mode of DES
664 static void
665 cbcauth(void)
667 register int n, j; /* number of bytes actually read */
668 Desbuf msgbuf; /* I/O buffer */
669 Desbuf encbuf; /* encryption buffer */
672 * do the transformation
673 * note we DISCARD the encrypted block;
674 * we only care about the last one
676 while ((n = READ(BUFFER(msgbuf), 8)) == 8) {
677 for (n = 0; n < 8; n++)
678 CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
679 DES_XFORM(UBUFFER(encbuf));
680 MEMCPY(BUFFER(ivec), BUFFER(encbuf), 8);
683 * now compute the last one, right padding with '\0' if need be
685 if (n > 0) {
686 MEMZERO(&CHAR(msgbuf, n), 8 - n);
687 for (n = 0; n < 8; n++)
688 CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
689 DES_XFORM(UBUFFER(encbuf));
692 * drop the bits
693 * we write chars until fewer than 7 bits,
694 * and then pad the last one with 0 bits
696 for (n = 0; macbits > 7; n++, macbits -= 8)
697 (void)putchar(CHAR(encbuf, n));
698 if (macbits > 0) {
699 CHAR(msgbuf, 0) = 0x00;
700 for (j = 0; j < macbits; j++)
701 CHAR(msgbuf, 0) |= (CHAR(encbuf, n)&bits[j]);
702 (void)putchar(CHAR(msgbuf, 0));
707 * This encrypts using the Cipher FeedBack mode of DES
709 static void
710 cfbenc(void)
712 register int n; /* number of bytes actually read */
713 register int nbytes; /* number of bytes to read */
714 register int bn; /* block number */
715 char ibuf[8]; /* input buffer */
716 Desbuf msgbuf; /* encryption buffer */
719 * do things in bytes, not bits
721 nbytes = fbbits / 8;
723 * do the transformation
725 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
726 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
727 DES_XFORM(UBUFFER(msgbuf));
728 for (n = 0; n < 8 - nbytes; n++)
729 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
730 for (n = 0; n < nbytes; n++)
731 UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
732 WRITE(&CHAR(ivec, 8-nbytes), nbytes);
735 * at EOF or last block -- in either case, the last byte contains
736 * the character representation of the number of bytes in it
738 bn++;
739 MEMZERO(&ibuf[n], nbytes - n);
740 ibuf[nbytes - 1] = n;
741 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
742 DES_XFORM(UBUFFER(msgbuf));
743 for (n = 0; n < nbytes; n++)
744 ibuf[n] ^= UCHAR(msgbuf, n);
745 WRITE(ibuf, nbytes);
749 * This decrypts using the Cipher Block Chaining mode of DES
751 static void
752 cfbdec(void)
754 register int n; /* number of bytes actually read */
755 register int c; /* used to test for EOF */
756 register int nbytes; /* number of bytes to read */
757 register int bn; /* block number */
758 char ibuf[8]; /* input buffer */
759 char obuf[8]; /* output buffer */
760 Desbuf msgbuf; /* encryption buffer */
763 * do things in bytes, not bits
765 nbytes = fbbits / 8;
767 * do the transformation
769 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
770 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
771 DES_XFORM(UBUFFER(msgbuf));
772 for (c = 0; c < 8 - nbytes; c++)
773 CHAR(ivec, c) = CHAR(ivec, c+nbytes);
774 for (c = 0; c < nbytes; c++) {
775 CHAR(ivec, 8-nbytes+c) = ibuf[c];
776 obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
779 * if the last one, handle it specially
781 if ((c = getchar()) == EOF) {
782 n = obuf[nbytes-1];
783 if (n < 0 || n > nbytes-1)
784 bdes_err(bn,
785 "decryption failed (block corrupted)");
787 else
788 (void)ungetc(c, stdin);
789 WRITE(obuf, n);
791 if (n > 0)
792 bdes_err(bn, "decryption failed (incomplete block)");
796 * This encrypts using the alternative Cipher FeedBack mode of DES
798 static void
799 cfbaenc(void)
801 register int n; /* number of bytes actually read */
802 register int nbytes; /* number of bytes to read */
803 register int bn; /* block number */
804 char ibuf[8]; /* input buffer */
805 char obuf[8]; /* output buffer */
806 Desbuf msgbuf; /* encryption buffer */
809 * do things in bytes, not bits
811 nbytes = fbbits / 7;
813 * do the transformation
815 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
816 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
817 DES_XFORM(UBUFFER(msgbuf));
818 for (n = 0; n < 8 - nbytes; n++)
819 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
820 for (n = 0; n < nbytes; n++)
821 UCHAR(ivec, 8-nbytes+n) = (ibuf[n] ^ UCHAR(msgbuf, n))
822 |0200;
823 for (n = 0; n < nbytes; n++)
824 obuf[n] = CHAR(ivec, 8-nbytes+n)&0177;
825 WRITE(obuf, nbytes);
828 * at EOF or last block -- in either case, the last byte contains
829 * the character representation of the number of bytes in it
831 bn++;
832 MEMZERO(&ibuf[n], nbytes - n);
833 ibuf[nbytes - 1] = ('0' + n)|0200;
834 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
835 DES_XFORM(UBUFFER(msgbuf));
836 for (n = 0; n < nbytes; n++)
837 ibuf[n] ^= UCHAR(msgbuf, n);
838 WRITE(ibuf, nbytes);
842 * This decrypts using the alternative Cipher Block Chaining mode of DES
844 static void
845 cfbadec(void)
847 register int n; /* number of bytes actually read */
848 register int c; /* used to test for EOF */
849 register int nbytes; /* number of bytes to read */
850 register int bn; /* block number */
851 char ibuf[8]; /* input buffer */
852 char obuf[8]; /* output buffer */
853 Desbuf msgbuf; /* encryption buffer */
856 * do things in bytes, not bits
858 nbytes = fbbits / 7;
860 * do the transformation
862 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
863 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
864 DES_XFORM(UBUFFER(msgbuf));
865 for (c = 0; c < 8 - nbytes; c++)
866 CHAR(ivec, c) = CHAR(ivec, c+nbytes);
867 for (c = 0; c < nbytes; c++) {
868 CHAR(ivec, 8-nbytes+c) = ibuf[c]|0200;
869 obuf[c] = (ibuf[c] ^ UCHAR(msgbuf, c))&0177;
872 * if the last one, handle it specially
874 if ((c = getchar()) == EOF) {
875 if ((n = (obuf[nbytes-1] - '0')) < 0
876 || n > nbytes-1)
877 bdes_err(bn,
878 "decryption failed (block corrupted)");
880 else
881 (void)ungetc(c, stdin);
882 WRITE(obuf, n);
884 if (n > 0)
885 bdes_err(bn, "decryption failed (incomplete block)");
890 * This encrypts using the Output FeedBack mode of DES
892 static void
893 ofbenc(void)
895 register int n; /* number of bytes actually read */
896 register int c; /* used to test for EOF */
897 register int nbytes; /* number of bytes to read */
898 register int bn; /* block number */
899 char ibuf[8]; /* input buffer */
900 char obuf[8]; /* output buffer */
901 Desbuf msgbuf; /* encryption buffer */
904 * do things in bytes, not bits
906 nbytes = fbbits / 8;
908 * do the transformation
910 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
911 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
912 DES_XFORM(UBUFFER(msgbuf));
913 for (n = 0; n < 8 - nbytes; n++)
914 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
915 for (n = 0; n < nbytes; n++) {
916 UCHAR(ivec, 8-nbytes+n) = UCHAR(msgbuf, n);
917 obuf[n] = ibuf[n] ^ UCHAR(msgbuf, n);
919 WRITE(obuf, nbytes);
922 * at EOF or last block -- in either case, the last byte contains
923 * the character representation of the number of bytes in it
925 bn++;
926 MEMZERO(&ibuf[n], nbytes - n);
927 ibuf[nbytes - 1] = n;
928 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
929 DES_XFORM(UBUFFER(msgbuf));
930 for (c = 0; c < nbytes; c++)
931 ibuf[c] ^= UCHAR(msgbuf, c);
932 WRITE(ibuf, nbytes);
936 * This decrypts using the Output Block Chaining mode of DES
938 static void
939 ofbdec(void)
941 register int n; /* number of bytes actually read */
942 register int c; /* used to test for EOF */
943 register int nbytes; /* number of bytes to read */
944 register int bn; /* block number */
945 char ibuf[8]; /* input buffer */
946 char obuf[8]; /* output buffer */
947 Desbuf msgbuf; /* encryption buffer */
950 * do things in bytes, not bits
952 nbytes = fbbits / 8;
954 * do the transformation
956 for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
957 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
958 DES_XFORM(UBUFFER(msgbuf));
959 for (c = 0; c < 8 - nbytes; c++)
960 CHAR(ivec, c) = CHAR(ivec, c+nbytes);
961 for (c = 0; c < nbytes; c++) {
962 CHAR(ivec, 8-nbytes+c) = UCHAR(msgbuf, c);
963 obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
966 * if the last one, handle it specially
968 if ((c = getchar()) == EOF) {
969 n = obuf[nbytes-1];
970 if (n < 0 || n > nbytes-1)
971 bdes_err(bn,
972 "decryption failed (block corrupted)");
974 else
975 (void)ungetc(c, stdin);
977 * dump it
979 WRITE(obuf, n);
981 if (n > 0)
982 bdes_err(bn, "decryption failed (incomplete block)");
986 * This authenticates using the Cipher FeedBack mode of DES
988 static void
989 cfbauth(void)
991 register int n, j; /* number of bytes actually read */
992 register int nbytes; /* number of bytes to read */
993 char ibuf[8]; /* input buffer */
994 Desbuf msgbuf; /* encryption buffer */
997 * do things in bytes, not bits
999 nbytes = fbbits / 8;
1001 * do the transformation
1003 while ((n = READ(ibuf, nbytes)) == nbytes) {
1004 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1005 DES_XFORM(UBUFFER(msgbuf));
1006 for (n = 0; n < 8 - nbytes; n++)
1007 UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
1008 for (n = 0; n < nbytes; n++)
1009 UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
1012 * at EOF or last block -- in either case, the last byte contains
1013 * the character representation of the number of bytes in it
1015 MEMZERO(&ibuf[n], nbytes - n);
1016 ibuf[nbytes - 1] = '0' + n;
1017 MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1018 DES_XFORM(UBUFFER(msgbuf));
1019 for (n = 0; n < nbytes; n++)
1020 ibuf[n] ^= UCHAR(msgbuf, n);
1022 * drop the bits
1023 * we write chars until fewer than 7 bits,
1024 * and then pad the last one with 0 bits
1026 for (n = 0; macbits > 7; n++, macbits -= 8)
1027 (void)putchar(CHAR(msgbuf, n));
1028 if (macbits > 0) {
1029 CHAR(msgbuf, 0) = 0x00;
1030 for (j = 0; j < macbits; j++)
1031 CHAR(msgbuf, 0) |= (CHAR(msgbuf, n)&bits[j]);
1032 (void)putchar(CHAR(msgbuf, 0));
1036 #ifndef FASTWAY
1038 * change from 8 bits/Uchar to 1 bit/Uchar
1040 static void
1041 expand(Desbuf from, char *to)
1043 register int i, j; /* counters in for loop */
1045 for (i = 0; i < 8; i++)
1046 for (j = 0; j < 8; j++)
1047 *to++ = (CHAR(from, i)>>(7-j))&01;
1051 * change from 1 bit/char to 8 bits/Uchar
1053 static void
1054 compress(char *from, Desbuf to)
1056 register int i, j; /* counters in for loop */
1058 for (i = 0; i < 8; i++) {
1059 CHAR(to, i) = 0;
1060 for (j = 0; j < 8; j++)
1061 CHAR(to, i) = ((*from++)<<(7-j))|CHAR(to, i);
1064 #endif
1067 * message about usage
1069 static void
1070 usage(void)
1073 (void) fprintf(stderr, "usage: %s %s\n", getprogname(),
1074 "[-abdp] [-F bit] [-f bit] [-k key] [-m bit] [-o bit] [-v vector]");
1075 exit(1);