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