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