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