1*0aa2b642Sandvar /* $NetBSD: bdes.c,v 1.11 2023/06/27 19:30:27 andvar Exp $ */
2468b4841Sthorpej
3468b4841Sthorpej /*-
4468b4841Sthorpej * Copyright (c) 1991, 1993
5468b4841Sthorpej * The Regents of the University of California. All rights reserved.
6468b4841Sthorpej *
7468b4841Sthorpej * This code is derived from software contributed to Berkeley by
8468b4841Sthorpej * Matt Bishop of Dartmouth College.
9468b4841Sthorpej *
10468b4841Sthorpej * The United States Government has rights in this work pursuant
11468b4841Sthorpej * to contract no. NAG 2-680 between the National Aeronautics and
12468b4841Sthorpej * Space Administration and Dartmouth College.
13468b4841Sthorpej *
14468b4841Sthorpej * Redistribution and use in source and binary forms, with or without
15468b4841Sthorpej * modification, are permitted provided that the following conditions
16468b4841Sthorpej * are met:
17468b4841Sthorpej * 1. Redistributions of source code must retain the above copyright
18468b4841Sthorpej * notice, this list of conditions and the following disclaimer.
19468b4841Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
20468b4841Sthorpej * notice, this list of conditions and the following disclaimer in the
21468b4841Sthorpej * documentation and/or other materials provided with the distribution.
2289aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
23468b4841Sthorpej * may be used to endorse or promote products derived from this software
24468b4841Sthorpej * without specific prior written permission.
25468b4841Sthorpej *
26468b4841Sthorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27468b4841Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28468b4841Sthorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29468b4841Sthorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30468b4841Sthorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31468b4841Sthorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32468b4841Sthorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33468b4841Sthorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34468b4841Sthorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35468b4841Sthorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36468b4841Sthorpej * SUCH DAMAGE.
37468b4841Sthorpej */
38468b4841Sthorpej
3993bf7731Sthorpej #include <sys/cdefs.h>
40468b4841Sthorpej #ifndef lint
4198e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
4298e5374cSlukem The Regents of the University of California. All rights reserved.");
43468b4841Sthorpej #endif /* not lint */
44468b4841Sthorpej
45468b4841Sthorpej #ifndef lint
46468b4841Sthorpej #if 0
47468b4841Sthorpej static char sccsid[] = "@(#)bdes.c 8.1 (Berkeley) 6/6/93";
48468b4841Sthorpej #else
49*0aa2b642Sandvar __RCSID("$NetBSD: bdes.c,v 1.11 2023/06/27 19:30:27 andvar Exp $");
50468b4841Sthorpej #endif
51468b4841Sthorpej #endif /* not lint */
52468b4841Sthorpej
53468b4841Sthorpej /*
54468b4841Sthorpej * BDES -- DES encryption package for Berkeley Software Distribution 4.4
55468b4841Sthorpej * options:
56468b4841Sthorpej * -a key is in ASCII
57468b4841Sthorpej * -b use ECB (electronic code book) mode
58468b4841Sthorpej * -d invert (decrypt) input
59468b4841Sthorpej * -f b use b-bit CFB (cipher feedback) mode
60468b4841Sthorpej * -F b use b-bit CFB (cipher feedback) alternative mode
61468b4841Sthorpej * -k key use key as the cryptographic key
62468b4841Sthorpej * -m b generate a MAC of length b
63468b4841Sthorpej * -o b use b-bit OFB (output feedback) mode
64468b4841Sthorpej * -p don't reset the parity bit
65468b4841Sthorpej * -v v use v as the initialization vector (ignored for ECB)
66468b4841Sthorpej * note: the last character of the last block is the integer indicating
67468b4841Sthorpej * how many characters of that block are to be output
68468b4841Sthorpej *
69468b4841Sthorpej * Author: Matt Bishop
70468b4841Sthorpej * Department of Mathematics and Computer Science
71468b4841Sthorpej * Dartmouth College
72468b4841Sthorpej * Hanover, NH 03755
73468b4841Sthorpej * Email: Matt.Bishop@dartmouth.edu
74468b4841Sthorpej * ...!decvax!dartvax!Matt.Bishop
75468b4841Sthorpej *
76468b4841Sthorpej * See Technical Report PCS-TR91-158, Department of Mathematics and Computer
77468b4841Sthorpej * Science, Dartmouth College, for a detailed description of the implemen-
78468b4841Sthorpej * tation and differences between it and Sun's. The DES is described in
79468b4841Sthorpej * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page
80468b4841Sthorpej * or the technical report for a complete reference).
81468b4841Sthorpej */
82468b4841Sthorpej
83468b4841Sthorpej #include <errno.h>
84468b4841Sthorpej #include <unistd.h>
85468b4841Sthorpej #include <stdio.h>
86468b4841Sthorpej #include <ctype.h>
87468b4841Sthorpej #include <stdlib.h>
88468b4841Sthorpej #include <string.h>
89468b4841Sthorpej
90468b4841Sthorpej /*
91468b4841Sthorpej * BSD and System V systems offer special library calls that do
92468b4841Sthorpej * block moves and fills, so if possible we take advantage of them
93468b4841Sthorpej */
94468b4841Sthorpej #define MEMCPY(dest,src,len) bcopy((src),(dest),(len))
95468b4841Sthorpej #define MEMZERO(dest,len) bzero((dest),(len))
96468b4841Sthorpej
97468b4841Sthorpej /* Hide the calls to the primitive encryption routines. */
98468b4841Sthorpej #define FASTWAY
99468b4841Sthorpej #ifdef FASTWAY
100468b4841Sthorpej #define DES_KEY(buf) \
101468b4841Sthorpej if (des_setkey(buf)) \
10293bf7731Sthorpej bdes_err(0, "des_setkey");
103468b4841Sthorpej #define DES_XFORM(buf) \
104468b4841Sthorpej if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
10593bf7731Sthorpej bdes_err(0, "des_cipher");
106468b4841Sthorpej #else
107468b4841Sthorpej #define DES_KEY(buf) { \
108468b4841Sthorpej char bits1[64]; /* bits of key */ \
109468b4841Sthorpej expand(buf, bits1); \
110468b4841Sthorpej if (setkey(bits1)) \
11193bf7731Sthorpej bdes_err(0, "setkey"); \
112468b4841Sthorpej }
113468b4841Sthorpej #define DES_XFORM(buf) { \
114468b4841Sthorpej char bits1[64]; /* bits of message */ \
115468b4841Sthorpej expand(buf, bits1); \
116468b4841Sthorpej if (encrypt(bits1, inverse)) \
11793bf7731Sthorpej bdes_err(0, "encrypt"); \
118468b4841Sthorpej compress(bits1, buf); \
119468b4841Sthorpej }
120468b4841Sthorpej #endif
121468b4841Sthorpej
122468b4841Sthorpej /*
123468b4841Sthorpej * this does an error-checking write
124468b4841Sthorpej */
125468b4841Sthorpej #define READ(buf, n) fread(buf, sizeof(char), n, stdin)
126468b4841Sthorpej #define WRITE(buf,n) \
127238e973fSlukem if (fwrite(buf, sizeof(char), n, stdout) != (size_t)n) \
12893bf7731Sthorpej bdes_err(bn, NULL);
129468b4841Sthorpej
130468b4841Sthorpej /*
131468b4841Sthorpej * some things to make references easier
132468b4841Sthorpej */
133468b4841Sthorpej typedef char Desbuf[8];
134468b4841Sthorpej #define CHAR(x,i) (x[i])
135468b4841Sthorpej #define UCHAR(x,i) (x[i])
136468b4841Sthorpej #define BUFFER(x) (x)
137468b4841Sthorpej #define UBUFFER(x) (x)
138468b4841Sthorpej
139468b4841Sthorpej /*
140468b4841Sthorpej * global variables and related macros
141468b4841Sthorpej */
142468b4841Sthorpej #define KEY_DEFAULT 0 /* interpret radix of key from key */
143468b4841Sthorpej #define KEY_ASCII 1 /* key is in ASCII characters */
144d9a44d71Sjoerg static int keybase = KEY_DEFAULT; /* how to interpret the key */
145468b4841Sthorpej
146d9a44d71Sjoerg static enum { /* encrypt, decrypt, authenticate */
147468b4841Sthorpej MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
148468b4841Sthorpej } mode = MODE_ENCRYPT;
149d9a44d71Sjoerg static enum { /* ecb, cbc, cfb, cfba, ofb? */
150468b4841Sthorpej ALG_ECB, ALG_CBC, ALG_CFB, ALG_OFB, ALG_CFBA
151468b4841Sthorpej } alg = ALG_CBC;
152468b4841Sthorpej
153d9a44d71Sjoerg static Desbuf ivec; /* initialization vector */
154d9a44d71Sjoerg static const char bits[] = { /* used to extract bits from a char */
155468b4841Sthorpej '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
156468b4841Sthorpej };
157d9a44d71Sjoerg static int inverse; /* 0 to encrypt, 1 to decrypt */
158d9a44d71Sjoerg static int macbits = -1; /* number of bits in authentication */
159d9a44d71Sjoerg static int fbbits = -1; /* number of feedback bits */
160d9a44d71Sjoerg static int pflag; /* 1 to preserve parity bits */
161468b4841Sthorpej
162d9a44d71Sjoerg static int setbits(char *, int);
163d9a44d71Sjoerg static void bdes_err(int, const char *) __dead;
164d9a44d71Sjoerg static int tobinhex(char, int);
165d9a44d71Sjoerg static void cvtkey(char *, char *);
166d9a44d71Sjoerg static void makekey(Desbuf);
167d9a44d71Sjoerg static void ecbenc(void);
168d9a44d71Sjoerg static void ecbdec(void);
169d9a44d71Sjoerg static void cbcenc(void);
170d9a44d71Sjoerg static void cbcdec(void);
171d9a44d71Sjoerg static void cbcauth(void);
172d9a44d71Sjoerg static void cfbenc(void);
173d9a44d71Sjoerg static void cfbdec(void);
174d9a44d71Sjoerg static void cfbaenc(void);
175d9a44d71Sjoerg static void cfbadec(void);
176d9a44d71Sjoerg static void ofbenc(void);
177d9a44d71Sjoerg static void ofbdec(void);
178d9a44d71Sjoerg static void cfbauth(void);
179d9a44d71Sjoerg #ifndef FASTWAY
180d9a44d71Sjoerg static void expand(Desbuf, char *);
181d9a44d71Sjoerg static void compress(char *, Desbuf);
182d9a44d71Sjoerg #endif
183d9a44d71Sjoerg static void usage(void) __dead;
18493bf7731Sthorpej
18593bf7731Sthorpej int
main(int ac,char * av[])18693bf7731Sthorpej main(int ac, char *av[])
187468b4841Sthorpej {
188468b4841Sthorpej register int i; /* counter in a for loop */
189468b4841Sthorpej register char *p; /* used to obtain the key */
190468b4841Sthorpej Desbuf msgbuf; /* I/O buffer */
191*0aa2b642Sandvar int kflag; /* command-line encryption key */
192468b4841Sthorpej int argc; /* the real arg count */
193468b4841Sthorpej char **argv; /* the real argument vector */
194468b4841Sthorpej
195468b4841Sthorpej /*
196468b4841Sthorpej * Hide the arguments from ps(1) by making private copies of them
197468b4841Sthorpej * and clobbering the global (visible to ps(1)) ones.
198468b4841Sthorpej */
199468b4841Sthorpej argc = ac;
200468b4841Sthorpej ac = 1;
201468b4841Sthorpej argv = malloc((argc + 1) * sizeof(char *));
202468b4841Sthorpej for (i = 0; i < argc; ++i) {
203468b4841Sthorpej argv[i] = strdup(av[i]);
204468b4841Sthorpej MEMZERO(av[i], strlen(av[i]));
205468b4841Sthorpej }
206468b4841Sthorpej argv[argc] = NULL;
207468b4841Sthorpej
208468b4841Sthorpej /* initialize the initialization vctor */
209468b4841Sthorpej MEMZERO(ivec, 8);
210468b4841Sthorpej
211468b4841Sthorpej /* process the argument list */
212468b4841Sthorpej kflag = 0;
213b46ec3b2Smjl while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1)
214468b4841Sthorpej switch(i) {
215468b4841Sthorpej case 'a': /* key is ASCII */
216468b4841Sthorpej keybase = KEY_ASCII;
217468b4841Sthorpej break;
218468b4841Sthorpej case 'b': /* use ECB mode */
219468b4841Sthorpej alg = ALG_ECB;
220468b4841Sthorpej break;
221468b4841Sthorpej case 'd': /* decrypt */
222468b4841Sthorpej mode = MODE_DECRYPT;
223468b4841Sthorpej break;
224468b4841Sthorpej case 'F': /* use alternative CFB mode */
225468b4841Sthorpej alg = ALG_CFBA;
226468b4841Sthorpej if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0)
22793bf7731Sthorpej bdes_err(-1,
22893bf7731Sthorpej "-F: number must be 1-56 inclusive");
229468b4841Sthorpej else if (fbbits == -1)
23093bf7731Sthorpej bdes_err(-1,
23193bf7731Sthorpej "-F: number must be a multiple of 7");
232468b4841Sthorpej break;
233468b4841Sthorpej case 'f': /* use CFB mode */
234468b4841Sthorpej alg = ALG_CFB;
235468b4841Sthorpej if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
23693bf7731Sthorpej bdes_err(-1,
23793bf7731Sthorpej "-f: number must be 1-64 inclusive");
238468b4841Sthorpej else if (fbbits == -1)
23993bf7731Sthorpej bdes_err(-1,
24093bf7731Sthorpej "-f: number must be a multiple of 8");
241468b4841Sthorpej break;
242468b4841Sthorpej case 'k': /* encryption key */
243468b4841Sthorpej kflag = 1;
244468b4841Sthorpej cvtkey(BUFFER(msgbuf), optarg);
245468b4841Sthorpej break;
246468b4841Sthorpej case 'm': /* number of bits for MACing */
247468b4841Sthorpej mode = MODE_AUTHENTICATE;
248468b4841Sthorpej if ((macbits = setbits(optarg, 1)) > 64)
24993bf7731Sthorpej bdes_err(-1,
25093bf7731Sthorpej "-m: number must be 0-64 inclusive");
251468b4841Sthorpej break;
252468b4841Sthorpej case 'o': /* use OFB mode */
253468b4841Sthorpej alg = ALG_OFB;
254468b4841Sthorpej if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0)
25593bf7731Sthorpej bdes_err(-1,
25693bf7731Sthorpej "-o: number must be 1-64 inclusive");
257468b4841Sthorpej else if (fbbits == -1)
25893bf7731Sthorpej bdes_err(-1,
25993bf7731Sthorpej "-o: number must be a multiple of 8");
260468b4841Sthorpej break;
261468b4841Sthorpej case 'p': /* preserve parity bits */
262468b4841Sthorpej pflag = 1;
263468b4841Sthorpej break;
264468b4841Sthorpej case 'v': /* set initialization vector */
265468b4841Sthorpej cvtkey(BUFFER(ivec), optarg);
266468b4841Sthorpej break;
267468b4841Sthorpej default: /* error */
268468b4841Sthorpej usage();
269468b4841Sthorpej }
270468b4841Sthorpej
271468b4841Sthorpej if (!kflag) {
272468b4841Sthorpej /*
273468b4841Sthorpej * if the key's not ASCII, assume it is
274468b4841Sthorpej */
275468b4841Sthorpej keybase = KEY_ASCII;
276468b4841Sthorpej /*
277468b4841Sthorpej * get the key
278468b4841Sthorpej */
279468b4841Sthorpej p = getpass("Enter key: ");
280468b4841Sthorpej /*
281468b4841Sthorpej * copy it, nul-padded, into the key area
282468b4841Sthorpej */
283468b4841Sthorpej cvtkey(BUFFER(msgbuf), p);
284468b4841Sthorpej }
285468b4841Sthorpej
286468b4841Sthorpej makekey(msgbuf);
287468b4841Sthorpej inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT;
288468b4841Sthorpej
289468b4841Sthorpej switch(alg) {
290468b4841Sthorpej case ALG_CBC:
291468b4841Sthorpej switch(mode) {
292468b4841Sthorpej case MODE_AUTHENTICATE: /* authenticate using CBC mode */
293468b4841Sthorpej cbcauth();
294468b4841Sthorpej break;
295468b4841Sthorpej case MODE_DECRYPT: /* decrypt using CBC mode */
296468b4841Sthorpej cbcdec();
297468b4841Sthorpej break;
298468b4841Sthorpej case MODE_ENCRYPT: /* encrypt using CBC mode */
299468b4841Sthorpej cbcenc();
300468b4841Sthorpej break;
301468b4841Sthorpej }
302468b4841Sthorpej break;
303468b4841Sthorpej case ALG_CFB:
304468b4841Sthorpej switch(mode) {
305468b4841Sthorpej case MODE_AUTHENTICATE: /* authenticate using CFB mode */
306468b4841Sthorpej cfbauth();
307468b4841Sthorpej break;
308468b4841Sthorpej case MODE_DECRYPT: /* decrypt using CFB mode */
309468b4841Sthorpej cfbdec();
310468b4841Sthorpej break;
311468b4841Sthorpej case MODE_ENCRYPT: /* encrypt using CFB mode */
312468b4841Sthorpej cfbenc();
313468b4841Sthorpej break;
314468b4841Sthorpej }
315468b4841Sthorpej break;
316468b4841Sthorpej case ALG_CFBA:
317468b4841Sthorpej switch(mode) {
318468b4841Sthorpej case MODE_AUTHENTICATE: /* authenticate using CFBA mode */
31993bf7731Sthorpej bdes_err(-1, "can't authenticate with CFBA mode");
320468b4841Sthorpej break;
321468b4841Sthorpej case MODE_DECRYPT: /* decrypt using CFBA mode */
322468b4841Sthorpej cfbadec();
323468b4841Sthorpej break;
324468b4841Sthorpej case MODE_ENCRYPT: /* encrypt using CFBA mode */
325468b4841Sthorpej cfbaenc();
326468b4841Sthorpej break;
327468b4841Sthorpej }
328468b4841Sthorpej break;
329468b4841Sthorpej case ALG_ECB:
330468b4841Sthorpej switch(mode) {
331468b4841Sthorpej case MODE_AUTHENTICATE: /* authenticate using ECB mode */
33293bf7731Sthorpej bdes_err(-1, "can't authenticate with ECB mode");
333468b4841Sthorpej break;
334468b4841Sthorpej case MODE_DECRYPT: /* decrypt using ECB mode */
335468b4841Sthorpej ecbdec();
336468b4841Sthorpej break;
337468b4841Sthorpej case MODE_ENCRYPT: /* encrypt using ECB mode */
338468b4841Sthorpej ecbenc();
339468b4841Sthorpej break;
340468b4841Sthorpej }
341468b4841Sthorpej break;
342468b4841Sthorpej case ALG_OFB:
343468b4841Sthorpej switch(mode) {
344468b4841Sthorpej case MODE_AUTHENTICATE: /* authenticate using OFB mode */
34593bf7731Sthorpej bdes_err(-1, "can't authenticate with OFB mode");
346468b4841Sthorpej break;
347468b4841Sthorpej case MODE_DECRYPT: /* decrypt using OFB mode */
348468b4841Sthorpej ofbdec();
349468b4841Sthorpej break;
350468b4841Sthorpej case MODE_ENCRYPT: /* encrypt using OFB mode */
351468b4841Sthorpej ofbenc();
352468b4841Sthorpej break;
353468b4841Sthorpej }
354468b4841Sthorpej break;
355468b4841Sthorpej }
356468b4841Sthorpej exit(0);
357468b4841Sthorpej }
358468b4841Sthorpej
359468b4841Sthorpej /*
360468b4841Sthorpej * print a warning message and, possibly, terminate
361468b4841Sthorpej */
362d9a44d71Sjoerg static void
bdes_err(int n,const char * s)36393bf7731Sthorpej bdes_err(int n, const char *s)
364468b4841Sthorpej {
365468b4841Sthorpej if (n > 0)
366468b4841Sthorpej (void)fprintf(stderr, "bdes (block %d): ", n);
367468b4841Sthorpej else
368468b4841Sthorpej (void)fprintf(stderr, "bdes: ");
369468b4841Sthorpej (void)fprintf(stderr, "%s\n", s ? s : strerror(errno));
370468b4841Sthorpej exit(1);
371468b4841Sthorpej }
372468b4841Sthorpej
373468b4841Sthorpej /*
374468b4841Sthorpej * map a hex character to an integer
375468b4841Sthorpej */
376d9a44d71Sjoerg static int
tobinhex(char c,int radix)37793bf7731Sthorpej tobinhex(char c, int radix)
378468b4841Sthorpej {
379468b4841Sthorpej switch(c) {
380468b4841Sthorpej case '0': return(0x0);
381468b4841Sthorpej case '1': return(0x1);
382468b4841Sthorpej case '2': return(radix > 2 ? 0x2 : -1);
383468b4841Sthorpej case '3': return(radix > 3 ? 0x3 : -1);
384468b4841Sthorpej case '4': return(radix > 4 ? 0x4 : -1);
385468b4841Sthorpej case '5': return(radix > 5 ? 0x5 : -1);
386468b4841Sthorpej case '6': return(radix > 6 ? 0x6 : -1);
387468b4841Sthorpej case '7': return(radix > 7 ? 0x7 : -1);
388468b4841Sthorpej case '8': return(radix > 8 ? 0x8 : -1);
389468b4841Sthorpej case '9': return(radix > 9 ? 0x9 : -1);
390468b4841Sthorpej case 'A': case 'a': return(radix > 10 ? 0xa : -1);
391468b4841Sthorpej case 'B': case 'b': return(radix > 11 ? 0xb : -1);
392468b4841Sthorpej case 'C': case 'c': return(radix > 12 ? 0xc : -1);
393468b4841Sthorpej case 'D': case 'd': return(radix > 13 ? 0xd : -1);
394468b4841Sthorpej case 'E': case 'e': return(radix > 14 ? 0xe : -1);
395468b4841Sthorpej case 'F': case 'f': return(radix > 15 ? 0xf : -1);
396468b4841Sthorpej }
397468b4841Sthorpej /*
398468b4841Sthorpej * invalid character
399468b4841Sthorpej */
400468b4841Sthorpej return(-1);
401468b4841Sthorpej }
402468b4841Sthorpej
403468b4841Sthorpej /*
404468b4841Sthorpej * convert the key to a bit pattern
405468b4841Sthorpej */
406d9a44d71Sjoerg static void
cvtkey(char * obuf,char * ibuf)40793bf7731Sthorpej cvtkey(char *obuf, char *ibuf)
408468b4841Sthorpej {
409468b4841Sthorpej register int i, j; /* counter in a for loop */
410468b4841Sthorpej int nbuf[64]; /* used for hex/key translation */
411468b4841Sthorpej
412468b4841Sthorpej /*
413468b4841Sthorpej * just switch on the key base
414468b4841Sthorpej */
415468b4841Sthorpej switch(keybase) {
416468b4841Sthorpej case KEY_ASCII: /* ascii to integer */
417468b4841Sthorpej (void)strncpy(obuf, ibuf, 8);
418468b4841Sthorpej return;
419468b4841Sthorpej case KEY_DEFAULT: /* tell from context */
420468b4841Sthorpej /*
421468b4841Sthorpej * leading '0x' or '0X' == hex key
422468b4841Sthorpej */
423468b4841Sthorpej if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) {
424468b4841Sthorpej ibuf = &ibuf[2];
425468b4841Sthorpej /*
426468b4841Sthorpej * now translate it, bombing on any illegal hex digit
427468b4841Sthorpej */
42851d0c372Schristos for (i = 0; i < 16 && ibuf[i]; i++)
429468b4841Sthorpej if ((nbuf[i] = tobinhex(ibuf[i], 16)) == -1)
43093bf7731Sthorpej bdes_err(-1, "bad hex digit in key");
431468b4841Sthorpej while (i < 16)
432468b4841Sthorpej nbuf[i++] = 0;
433468b4841Sthorpej for (i = 0; i < 8; i++)
434468b4841Sthorpej obuf[i] =
435468b4841Sthorpej ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
436468b4841Sthorpej /* preserve parity bits */
437468b4841Sthorpej pflag = 1;
438468b4841Sthorpej return;
439468b4841Sthorpej }
440468b4841Sthorpej /*
441468b4841Sthorpej * leading '0b' or '0B' == binary key
442468b4841Sthorpej */
443468b4841Sthorpej if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) {
444468b4841Sthorpej ibuf = &ibuf[2];
445468b4841Sthorpej /*
446468b4841Sthorpej * now translate it, bombing on any illegal binary digit
447468b4841Sthorpej */
448468b4841Sthorpej for (i = 0; ibuf[i] && i < 16; i++)
449468b4841Sthorpej if ((nbuf[i] = tobinhex(ibuf[i], 2)) == -1)
45093bf7731Sthorpej bdes_err(-1, "bad binary digit in key");
451468b4841Sthorpej while (i < 64)
452468b4841Sthorpej nbuf[i++] = 0;
453468b4841Sthorpej for (i = 0; i < 8; i++)
454468b4841Sthorpej for (j = 0; j < 8; j++)
455468b4841Sthorpej obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
456468b4841Sthorpej /* preserve parity bits */
457468b4841Sthorpej pflag = 1;
458468b4841Sthorpej return;
459468b4841Sthorpej }
460468b4841Sthorpej /*
461468b4841Sthorpej * no special leader -- ASCII
462468b4841Sthorpej */
463468b4841Sthorpej (void)strncpy(obuf, ibuf, 8);
464468b4841Sthorpej }
465468b4841Sthorpej }
466468b4841Sthorpej
467468b4841Sthorpej /*
468468b4841Sthorpej * convert an ASCII string into a decimal number:
469f77de37cSdsl * 1. must be between 0 and 64 inclusive (or 56, checked by caller)
470468b4841Sthorpej * 2. must be a valid decimal number
471468b4841Sthorpej * 3. must be a multiple of mult
472468b4841Sthorpej */
473d9a44d71Sjoerg static int
setbits(char * s,int mult)47493bf7731Sthorpej setbits(char *s, int mult)
475468b4841Sthorpej {
476f77de37cSdsl char *p;
477f77de37cSdsl int n; /* the integer collected */
478468b4841Sthorpej
479f77de37cSdsl n = strtoul(s, &p, 10);
480f77de37cSdsl if (*p != 0)
48193bf7731Sthorpej bdes_err(-1, "bad decimal digit in MAC length");
482468b4841Sthorpej /*
483468b4841Sthorpej * be sure it's a multiple of mult
484468b4841Sthorpej */
485468b4841Sthorpej return((n % mult != 0) ? -1 : n);
486468b4841Sthorpej }
487468b4841Sthorpej
488468b4841Sthorpej /*****************
489468b4841Sthorpej * DES FUNCTIONS *
490468b4841Sthorpej *****************/
491468b4841Sthorpej /*
492468b4841Sthorpej * This sets the DES key and (if you're using the deszip version)
493468b4841Sthorpej * the direction of the transformation. This uses the Sun
494468b4841Sthorpej * to map the 64-bit key onto the 56 bits that the key schedule
495468b4841Sthorpej * generation routines use: the old way, which just uses the user-
496468b4841Sthorpej * supplied 64 bits as is, and the new way, which resets the parity
497468b4841Sthorpej * bit to be the same as the low-order bit in each character. The
498468b4841Sthorpej * new way generates a greater variety of key schedules, since many
499468b4841Sthorpej * systems set the parity (high) bit of each character to 0, and the
500468b4841Sthorpej * DES ignores the low order bit of each character.
501468b4841Sthorpej */
502d9a44d71Sjoerg static void
makekey(Desbuf buf)50393bf7731Sthorpej makekey(Desbuf buf)
504468b4841Sthorpej {
505468b4841Sthorpej register int i, j; /* counter in a for loop */
506468b4841Sthorpej register int par; /* parity counter */
507468b4841Sthorpej
508468b4841Sthorpej /*
509468b4841Sthorpej * if the parity is not preserved, flip it
510468b4841Sthorpej */
511468b4841Sthorpej if (!pflag) {
512468b4841Sthorpej for (i = 0; i < 8; i++) {
513468b4841Sthorpej par = 0;
514468b4841Sthorpej for (j = 1; j < 8; j++)
515468b4841Sthorpej if ((bits[j]&UCHAR(buf, i)) != 0)
516468b4841Sthorpej par++;
517468b4841Sthorpej if ((par&01) == 01)
518468b4841Sthorpej UCHAR(buf, i) = UCHAR(buf, i)&0177;
519468b4841Sthorpej else
520468b4841Sthorpej UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
521468b4841Sthorpej }
522468b4841Sthorpej }
523468b4841Sthorpej
524468b4841Sthorpej DES_KEY(UBUFFER(buf));
525468b4841Sthorpej }
526468b4841Sthorpej
527468b4841Sthorpej /*
528468b4841Sthorpej * This encrypts using the Electronic Code Book mode of DES
529468b4841Sthorpej */
530d9a44d71Sjoerg static void
ecbenc(void)53193bf7731Sthorpej ecbenc(void)
532468b4841Sthorpej {
533468b4841Sthorpej register int n; /* number of bytes actually read */
534468b4841Sthorpej register int bn; /* block number */
535468b4841Sthorpej Desbuf msgbuf; /* I/O buffer */
536468b4841Sthorpej
537468b4841Sthorpej for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
538468b4841Sthorpej /*
539468b4841Sthorpej * do the transformation
540468b4841Sthorpej */
541468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
542468b4841Sthorpej WRITE(BUFFER(msgbuf), 8);
543468b4841Sthorpej }
544468b4841Sthorpej /*
545468b4841Sthorpej * at EOF or last block -- in either ase, the last byte contains
546468b4841Sthorpej * the character representation of the number of bytes in it
547468b4841Sthorpej */
548468b4841Sthorpej bn++;
549468b4841Sthorpej MEMZERO(&CHAR(msgbuf, n), 8 - n);
550468b4841Sthorpej CHAR(msgbuf, 7) = n;
551468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
552468b4841Sthorpej WRITE(BUFFER(msgbuf), 8);
553468b4841Sthorpej
554468b4841Sthorpej }
555468b4841Sthorpej
556468b4841Sthorpej /*
557468b4841Sthorpej * This decrypts using the Electronic Code Book mode of DES
558468b4841Sthorpej */
559d9a44d71Sjoerg static void
ecbdec(void)56093bf7731Sthorpej ecbdec(void)
561468b4841Sthorpej {
562468b4841Sthorpej register int n; /* number of bytes actually read */
563468b4841Sthorpej register int c; /* used to test for EOF */
564468b4841Sthorpej register int bn; /* block number */
565468b4841Sthorpej Desbuf msgbuf; /* I/O buffer */
566468b4841Sthorpej
567468b4841Sthorpej for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
568468b4841Sthorpej /*
569468b4841Sthorpej * do the transformation
570468b4841Sthorpej */
571468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
572468b4841Sthorpej /*
573468b4841Sthorpej * if the last one, handle it specially
574468b4841Sthorpej */
575468b4841Sthorpej if ((c = getchar()) == EOF) {
576468b4841Sthorpej n = CHAR(msgbuf, 7);
577468b4841Sthorpej if (n < 0 || n > 7)
57893bf7731Sthorpej bdes_err(bn,
57993bf7731Sthorpej "decryption failed (block corrupted)");
580468b4841Sthorpej }
581468b4841Sthorpej else
582468b4841Sthorpej (void)ungetc(c, stdin);
583468b4841Sthorpej WRITE(BUFFER(msgbuf), n);
584468b4841Sthorpej }
585468b4841Sthorpej if (n > 0)
58693bf7731Sthorpej bdes_err(bn, "decryption failed (incomplete block)");
587468b4841Sthorpej }
588468b4841Sthorpej
589468b4841Sthorpej /*
590468b4841Sthorpej * This encrypts using the Cipher Block Chaining mode of DES
591468b4841Sthorpej */
592d9a44d71Sjoerg static void
cbcenc(void)59393bf7731Sthorpej cbcenc(void)
594468b4841Sthorpej {
595468b4841Sthorpej register int n; /* number of bytes actually read */
596468b4841Sthorpej register int bn; /* block number */
597468b4841Sthorpej Desbuf msgbuf; /* I/O buffer */
598468b4841Sthorpej
599468b4841Sthorpej /*
600468b4841Sthorpej * do the transformation
601468b4841Sthorpej */
602468b4841Sthorpej for (bn = 1; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
603468b4841Sthorpej for (n = 0; n < 8; n++)
604468b4841Sthorpej CHAR(msgbuf, n) ^= CHAR(ivec, n);
605468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
606468b4841Sthorpej MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
607468b4841Sthorpej WRITE(BUFFER(msgbuf), 8);
608468b4841Sthorpej }
609468b4841Sthorpej /*
610468b4841Sthorpej * at EOF or last block -- in either case, the last byte contains
611468b4841Sthorpej * the character representation of the number of bytes in it
612468b4841Sthorpej */
613468b4841Sthorpej bn++;
614468b4841Sthorpej MEMZERO(&CHAR(msgbuf, n), 8 - n);
615468b4841Sthorpej CHAR(msgbuf, 7) = n;
616468b4841Sthorpej for (n = 0; n < 8; n++)
617468b4841Sthorpej CHAR(msgbuf, n) ^= CHAR(ivec, n);
618468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
619468b4841Sthorpej WRITE(BUFFER(msgbuf), 8);
620468b4841Sthorpej
621468b4841Sthorpej }
622468b4841Sthorpej
623468b4841Sthorpej /*
624468b4841Sthorpej * This decrypts using the Cipher Block Chaining mode of DES
625468b4841Sthorpej */
626d9a44d71Sjoerg static void
cbcdec(void)62793bf7731Sthorpej cbcdec(void)
628468b4841Sthorpej {
629468b4841Sthorpej register int n; /* number of bytes actually read */
630468b4841Sthorpej Desbuf msgbuf; /* I/O buffer */
631468b4841Sthorpej Desbuf ibuf; /* temp buffer for initialization vector */
632468b4841Sthorpej register int c; /* used to test for EOF */
633468b4841Sthorpej register int bn; /* block number */
634468b4841Sthorpej
635468b4841Sthorpej for (bn = 0; (n = READ(BUFFER(msgbuf), 8)) == 8; bn++) {
636468b4841Sthorpej /*
637468b4841Sthorpej * do the transformation
638468b4841Sthorpej */
639468b4841Sthorpej MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8);
640468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
641468b4841Sthorpej for (c = 0; c < 8; c++)
642468b4841Sthorpej UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
643468b4841Sthorpej MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8);
644468b4841Sthorpej /*
645468b4841Sthorpej * if the last one, handle it specially
646468b4841Sthorpej */
647468b4841Sthorpej if ((c = getchar()) == EOF) {
648468b4841Sthorpej n = CHAR(msgbuf, 7);
649468b4841Sthorpej if (n < 0 || n > 7)
65093bf7731Sthorpej bdes_err(bn,
65193bf7731Sthorpej "decryption failed (block corrupted)");
652468b4841Sthorpej }
653468b4841Sthorpej else
654468b4841Sthorpej (void)ungetc(c, stdin);
655468b4841Sthorpej WRITE(BUFFER(msgbuf), n);
656468b4841Sthorpej }
657468b4841Sthorpej if (n > 0)
65893bf7731Sthorpej bdes_err(bn, "decryption failed (incomplete block)");
659468b4841Sthorpej }
660468b4841Sthorpej
661468b4841Sthorpej /*
662468b4841Sthorpej * This authenticates using the Cipher Block Chaining mode of DES
663468b4841Sthorpej */
664d9a44d71Sjoerg static void
cbcauth(void)66593bf7731Sthorpej cbcauth(void)
666468b4841Sthorpej {
667468b4841Sthorpej register int n, j; /* number of bytes actually read */
668468b4841Sthorpej Desbuf msgbuf; /* I/O buffer */
669468b4841Sthorpej Desbuf encbuf; /* encryption buffer */
670468b4841Sthorpej
671468b4841Sthorpej /*
672468b4841Sthorpej * do the transformation
673468b4841Sthorpej * note we DISCARD the encrypted block;
674468b4841Sthorpej * we only care about the last one
675468b4841Sthorpej */
676468b4841Sthorpej while ((n = READ(BUFFER(msgbuf), 8)) == 8) {
677468b4841Sthorpej for (n = 0; n < 8; n++)
678468b4841Sthorpej CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
679468b4841Sthorpej DES_XFORM(UBUFFER(encbuf));
680468b4841Sthorpej MEMCPY(BUFFER(ivec), BUFFER(encbuf), 8);
681468b4841Sthorpej }
682468b4841Sthorpej /*
683468b4841Sthorpej * now compute the last one, right padding with '\0' if need be
684468b4841Sthorpej */
685468b4841Sthorpej if (n > 0) {
686468b4841Sthorpej MEMZERO(&CHAR(msgbuf, n), 8 - n);
687468b4841Sthorpej for (n = 0; n < 8; n++)
688468b4841Sthorpej CHAR(encbuf, n) = CHAR(msgbuf, n) ^ CHAR(ivec, n);
689468b4841Sthorpej DES_XFORM(UBUFFER(encbuf));
690468b4841Sthorpej }
691468b4841Sthorpej /*
692468b4841Sthorpej * drop the bits
693468b4841Sthorpej * we write chars until fewer than 7 bits,
694468b4841Sthorpej * and then pad the last one with 0 bits
695468b4841Sthorpej */
696468b4841Sthorpej for (n = 0; macbits > 7; n++, macbits -= 8)
697468b4841Sthorpej (void)putchar(CHAR(encbuf, n));
698468b4841Sthorpej if (macbits > 0) {
699468b4841Sthorpej CHAR(msgbuf, 0) = 0x00;
700468b4841Sthorpej for (j = 0; j < macbits; j++)
701468b4841Sthorpej CHAR(msgbuf, 0) |= (CHAR(encbuf, n)&bits[j]);
702468b4841Sthorpej (void)putchar(CHAR(msgbuf, 0));
703468b4841Sthorpej }
704468b4841Sthorpej }
705468b4841Sthorpej
706468b4841Sthorpej /*
707468b4841Sthorpej * This encrypts using the Cipher FeedBack mode of DES
708468b4841Sthorpej */
709d9a44d71Sjoerg static void
cfbenc(void)71093bf7731Sthorpej cfbenc(void)
711468b4841Sthorpej {
712468b4841Sthorpej register int n; /* number of bytes actually read */
713468b4841Sthorpej register int nbytes; /* number of bytes to read */
714468b4841Sthorpej register int bn; /* block number */
715468b4841Sthorpej char ibuf[8]; /* input buffer */
716468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
717468b4841Sthorpej
718468b4841Sthorpej /*
719468b4841Sthorpej * do things in bytes, not bits
720468b4841Sthorpej */
721468b4841Sthorpej nbytes = fbbits / 8;
722468b4841Sthorpej /*
723468b4841Sthorpej * do the transformation
724468b4841Sthorpej */
725468b4841Sthorpej for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
726468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
727468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
728468b4841Sthorpej for (n = 0; n < 8 - nbytes; n++)
729468b4841Sthorpej UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
730468b4841Sthorpej for (n = 0; n < nbytes; n++)
731468b4841Sthorpej UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
732468b4841Sthorpej WRITE(&CHAR(ivec, 8-nbytes), nbytes);
733468b4841Sthorpej }
734468b4841Sthorpej /*
735468b4841Sthorpej * at EOF or last block -- in either case, the last byte contains
736468b4841Sthorpej * the character representation of the number of bytes in it
737468b4841Sthorpej */
738468b4841Sthorpej bn++;
739468b4841Sthorpej MEMZERO(&ibuf[n], nbytes - n);
740468b4841Sthorpej ibuf[nbytes - 1] = n;
741468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
742468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
743468b4841Sthorpej for (n = 0; n < nbytes; n++)
744468b4841Sthorpej ibuf[n] ^= UCHAR(msgbuf, n);
745468b4841Sthorpej WRITE(ibuf, nbytes);
746468b4841Sthorpej }
747468b4841Sthorpej
748468b4841Sthorpej /*
749468b4841Sthorpej * This decrypts using the Cipher Block Chaining mode of DES
750468b4841Sthorpej */
751d9a44d71Sjoerg static void
cfbdec(void)75293bf7731Sthorpej cfbdec(void)
753468b4841Sthorpej {
754468b4841Sthorpej register int n; /* number of bytes actually read */
755468b4841Sthorpej register int c; /* used to test for EOF */
756468b4841Sthorpej register int nbytes; /* number of bytes to read */
757468b4841Sthorpej register int bn; /* block number */
758468b4841Sthorpej char ibuf[8]; /* input buffer */
759468b4841Sthorpej char obuf[8]; /* output buffer */
760468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
761468b4841Sthorpej
762468b4841Sthorpej /*
763468b4841Sthorpej * do things in bytes, not bits
764468b4841Sthorpej */
765468b4841Sthorpej nbytes = fbbits / 8;
766468b4841Sthorpej /*
767468b4841Sthorpej * do the transformation
768468b4841Sthorpej */
769468b4841Sthorpej for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
770468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
771468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
772468b4841Sthorpej for (c = 0; c < 8 - nbytes; c++)
773468b4841Sthorpej CHAR(ivec, c) = CHAR(ivec, c+nbytes);
774468b4841Sthorpej for (c = 0; c < nbytes; c++) {
775468b4841Sthorpej CHAR(ivec, 8-nbytes+c) = ibuf[c];
776468b4841Sthorpej obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
777468b4841Sthorpej }
778468b4841Sthorpej /*
779468b4841Sthorpej * if the last one, handle it specially
780468b4841Sthorpej */
781468b4841Sthorpej if ((c = getchar()) == EOF) {
782468b4841Sthorpej n = obuf[nbytes-1];
783468b4841Sthorpej if (n < 0 || n > nbytes-1)
78493bf7731Sthorpej bdes_err(bn,
78593bf7731Sthorpej "decryption failed (block corrupted)");
786468b4841Sthorpej }
787468b4841Sthorpej else
788468b4841Sthorpej (void)ungetc(c, stdin);
789468b4841Sthorpej WRITE(obuf, n);
790468b4841Sthorpej }
791468b4841Sthorpej if (n > 0)
79293bf7731Sthorpej bdes_err(bn, "decryption failed (incomplete block)");
793468b4841Sthorpej }
794468b4841Sthorpej
795468b4841Sthorpej /*
796468b4841Sthorpej * This encrypts using the alternative Cipher FeedBack mode of DES
797468b4841Sthorpej */
798d9a44d71Sjoerg static void
cfbaenc(void)79993bf7731Sthorpej cfbaenc(void)
800468b4841Sthorpej {
801468b4841Sthorpej register int n; /* number of bytes actually read */
802468b4841Sthorpej register int nbytes; /* number of bytes to read */
803468b4841Sthorpej register int bn; /* block number */
804468b4841Sthorpej char ibuf[8]; /* input buffer */
805468b4841Sthorpej char obuf[8]; /* output buffer */
806468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
807468b4841Sthorpej
808468b4841Sthorpej /*
809468b4841Sthorpej * do things in bytes, not bits
810468b4841Sthorpej */
811468b4841Sthorpej nbytes = fbbits / 7;
812468b4841Sthorpej /*
813468b4841Sthorpej * do the transformation
814468b4841Sthorpej */
815468b4841Sthorpej for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
816468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
817468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
818468b4841Sthorpej for (n = 0; n < 8 - nbytes; n++)
819468b4841Sthorpej UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
820468b4841Sthorpej for (n = 0; n < nbytes; n++)
821468b4841Sthorpej UCHAR(ivec, 8-nbytes+n) = (ibuf[n] ^ UCHAR(msgbuf, n))
822468b4841Sthorpej |0200;
823468b4841Sthorpej for (n = 0; n < nbytes; n++)
824468b4841Sthorpej obuf[n] = CHAR(ivec, 8-nbytes+n)&0177;
825468b4841Sthorpej WRITE(obuf, nbytes);
826468b4841Sthorpej }
827468b4841Sthorpej /*
828468b4841Sthorpej * at EOF or last block -- in either case, the last byte contains
829468b4841Sthorpej * the character representation of the number of bytes in it
830468b4841Sthorpej */
831468b4841Sthorpej bn++;
832468b4841Sthorpej MEMZERO(&ibuf[n], nbytes - n);
833468b4841Sthorpej ibuf[nbytes - 1] = ('0' + n)|0200;
834468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
835468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
836468b4841Sthorpej for (n = 0; n < nbytes; n++)
837468b4841Sthorpej ibuf[n] ^= UCHAR(msgbuf, n);
838468b4841Sthorpej WRITE(ibuf, nbytes);
839468b4841Sthorpej }
840468b4841Sthorpej
841468b4841Sthorpej /*
842468b4841Sthorpej * This decrypts using the alternative Cipher Block Chaining mode of DES
843468b4841Sthorpej */
844d9a44d71Sjoerg static void
cfbadec(void)84593bf7731Sthorpej cfbadec(void)
846468b4841Sthorpej {
847468b4841Sthorpej register int n; /* number of bytes actually read */
848468b4841Sthorpej register int c; /* used to test for EOF */
849468b4841Sthorpej register int nbytes; /* number of bytes to read */
850468b4841Sthorpej register int bn; /* block number */
851468b4841Sthorpej char ibuf[8]; /* input buffer */
852468b4841Sthorpej char obuf[8]; /* output buffer */
853468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
854468b4841Sthorpej
855468b4841Sthorpej /*
856468b4841Sthorpej * do things in bytes, not bits
857468b4841Sthorpej */
858468b4841Sthorpej nbytes = fbbits / 7;
859468b4841Sthorpej /*
860468b4841Sthorpej * do the transformation
861468b4841Sthorpej */
862468b4841Sthorpej for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
863468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
864468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
865468b4841Sthorpej for (c = 0; c < 8 - nbytes; c++)
866468b4841Sthorpej CHAR(ivec, c) = CHAR(ivec, c+nbytes);
867468b4841Sthorpej for (c = 0; c < nbytes; c++) {
868468b4841Sthorpej CHAR(ivec, 8-nbytes+c) = ibuf[c]|0200;
869468b4841Sthorpej obuf[c] = (ibuf[c] ^ UCHAR(msgbuf, c))&0177;
870468b4841Sthorpej }
871468b4841Sthorpej /*
872468b4841Sthorpej * if the last one, handle it specially
873468b4841Sthorpej */
874468b4841Sthorpej if ((c = getchar()) == EOF) {
875468b4841Sthorpej if ((n = (obuf[nbytes-1] - '0')) < 0
876468b4841Sthorpej || n > nbytes-1)
87793bf7731Sthorpej bdes_err(bn,
87893bf7731Sthorpej "decryption failed (block corrupted)");
879468b4841Sthorpej }
880468b4841Sthorpej else
881468b4841Sthorpej (void)ungetc(c, stdin);
882468b4841Sthorpej WRITE(obuf, n);
883468b4841Sthorpej }
884468b4841Sthorpej if (n > 0)
88593bf7731Sthorpej bdes_err(bn, "decryption failed (incomplete block)");
886468b4841Sthorpej }
887468b4841Sthorpej
888468b4841Sthorpej
889468b4841Sthorpej /*
890468b4841Sthorpej * This encrypts using the Output FeedBack mode of DES
891468b4841Sthorpej */
892d9a44d71Sjoerg static void
ofbenc(void)89393bf7731Sthorpej ofbenc(void)
894468b4841Sthorpej {
895468b4841Sthorpej register int n; /* number of bytes actually read */
896468b4841Sthorpej register int c; /* used to test for EOF */
897468b4841Sthorpej register int nbytes; /* number of bytes to read */
898468b4841Sthorpej register int bn; /* block number */
899468b4841Sthorpej char ibuf[8]; /* input buffer */
900468b4841Sthorpej char obuf[8]; /* output buffer */
901468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
902468b4841Sthorpej
903468b4841Sthorpej /*
904468b4841Sthorpej * do things in bytes, not bits
905468b4841Sthorpej */
906468b4841Sthorpej nbytes = fbbits / 8;
907468b4841Sthorpej /*
908468b4841Sthorpej * do the transformation
909468b4841Sthorpej */
910468b4841Sthorpej for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
911468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
912468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
913468b4841Sthorpej for (n = 0; n < 8 - nbytes; n++)
914468b4841Sthorpej UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
915468b4841Sthorpej for (n = 0; n < nbytes; n++) {
916468b4841Sthorpej UCHAR(ivec, 8-nbytes+n) = UCHAR(msgbuf, n);
917468b4841Sthorpej obuf[n] = ibuf[n] ^ UCHAR(msgbuf, n);
918468b4841Sthorpej }
919468b4841Sthorpej WRITE(obuf, nbytes);
920468b4841Sthorpej }
921468b4841Sthorpej /*
922468b4841Sthorpej * at EOF or last block -- in either case, the last byte contains
923468b4841Sthorpej * the character representation of the number of bytes in it
924468b4841Sthorpej */
925468b4841Sthorpej bn++;
926468b4841Sthorpej MEMZERO(&ibuf[n], nbytes - n);
927468b4841Sthorpej ibuf[nbytes - 1] = n;
928468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
929468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
930468b4841Sthorpej for (c = 0; c < nbytes; c++)
931468b4841Sthorpej ibuf[c] ^= UCHAR(msgbuf, c);
932468b4841Sthorpej WRITE(ibuf, nbytes);
933468b4841Sthorpej }
934468b4841Sthorpej
935468b4841Sthorpej /*
936468b4841Sthorpej * This decrypts using the Output Block Chaining mode of DES
937468b4841Sthorpej */
938d9a44d71Sjoerg static void
ofbdec(void)93993bf7731Sthorpej ofbdec(void)
940468b4841Sthorpej {
941468b4841Sthorpej register int n; /* number of bytes actually read */
942468b4841Sthorpej register int c; /* used to test for EOF */
943468b4841Sthorpej register int nbytes; /* number of bytes to read */
944468b4841Sthorpej register int bn; /* block number */
945468b4841Sthorpej char ibuf[8]; /* input buffer */
946468b4841Sthorpej char obuf[8]; /* output buffer */
947468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
948468b4841Sthorpej
949468b4841Sthorpej /*
950468b4841Sthorpej * do things in bytes, not bits
951468b4841Sthorpej */
952468b4841Sthorpej nbytes = fbbits / 8;
953468b4841Sthorpej /*
954468b4841Sthorpej * do the transformation
955468b4841Sthorpej */
956468b4841Sthorpej for (bn = 1; (n = READ(ibuf, nbytes)) == nbytes; bn++) {
957468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
958468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
959468b4841Sthorpej for (c = 0; c < 8 - nbytes; c++)
960468b4841Sthorpej CHAR(ivec, c) = CHAR(ivec, c+nbytes);
961468b4841Sthorpej for (c = 0; c < nbytes; c++) {
962468b4841Sthorpej CHAR(ivec, 8-nbytes+c) = UCHAR(msgbuf, c);
963468b4841Sthorpej obuf[c] = ibuf[c] ^ UCHAR(msgbuf, c);
964468b4841Sthorpej }
965468b4841Sthorpej /*
966468b4841Sthorpej * if the last one, handle it specially
967468b4841Sthorpej */
968468b4841Sthorpej if ((c = getchar()) == EOF) {
969468b4841Sthorpej n = obuf[nbytes-1];
970468b4841Sthorpej if (n < 0 || n > nbytes-1)
97193bf7731Sthorpej bdes_err(bn,
97293bf7731Sthorpej "decryption failed (block corrupted)");
973468b4841Sthorpej }
974468b4841Sthorpej else
975468b4841Sthorpej (void)ungetc(c, stdin);
976468b4841Sthorpej /*
977468b4841Sthorpej * dump it
978468b4841Sthorpej */
979468b4841Sthorpej WRITE(obuf, n);
980468b4841Sthorpej }
981468b4841Sthorpej if (n > 0)
98293bf7731Sthorpej bdes_err(bn, "decryption failed (incomplete block)");
983468b4841Sthorpej }
984468b4841Sthorpej
985468b4841Sthorpej /*
986468b4841Sthorpej * This authenticates using the Cipher FeedBack mode of DES
987468b4841Sthorpej */
988d9a44d71Sjoerg static void
cfbauth(void)98993bf7731Sthorpej cfbauth(void)
990468b4841Sthorpej {
991468b4841Sthorpej register int n, j; /* number of bytes actually read */
992468b4841Sthorpej register int nbytes; /* number of bytes to read */
993468b4841Sthorpej char ibuf[8]; /* input buffer */
994468b4841Sthorpej Desbuf msgbuf; /* encryption buffer */
995468b4841Sthorpej
996468b4841Sthorpej /*
997468b4841Sthorpej * do things in bytes, not bits
998468b4841Sthorpej */
999468b4841Sthorpej nbytes = fbbits / 8;
1000468b4841Sthorpej /*
1001468b4841Sthorpej * do the transformation
1002468b4841Sthorpej */
1003468b4841Sthorpej while ((n = READ(ibuf, nbytes)) == nbytes) {
1004468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1005468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
1006468b4841Sthorpej for (n = 0; n < 8 - nbytes; n++)
1007468b4841Sthorpej UCHAR(ivec, n) = UCHAR(ivec, n+nbytes);
1008468b4841Sthorpej for (n = 0; n < nbytes; n++)
1009468b4841Sthorpej UCHAR(ivec, 8-nbytes+n) = ibuf[n] ^ UCHAR(msgbuf, n);
1010468b4841Sthorpej }
1011468b4841Sthorpej /*
1012468b4841Sthorpej * at EOF or last block -- in either case, the last byte contains
1013468b4841Sthorpej * the character representation of the number of bytes in it
1014468b4841Sthorpej */
1015468b4841Sthorpej MEMZERO(&ibuf[n], nbytes - n);
1016468b4841Sthorpej ibuf[nbytes - 1] = '0' + n;
1017468b4841Sthorpej MEMCPY(BUFFER(msgbuf), BUFFER(ivec), 8);
1018468b4841Sthorpej DES_XFORM(UBUFFER(msgbuf));
1019468b4841Sthorpej for (n = 0; n < nbytes; n++)
1020468b4841Sthorpej ibuf[n] ^= UCHAR(msgbuf, n);
1021468b4841Sthorpej /*
1022468b4841Sthorpej * drop the bits
1023468b4841Sthorpej * we write chars until fewer than 7 bits,
1024468b4841Sthorpej * and then pad the last one with 0 bits
1025468b4841Sthorpej */
1026468b4841Sthorpej for (n = 0; macbits > 7; n++, macbits -= 8)
1027468b4841Sthorpej (void)putchar(CHAR(msgbuf, n));
1028468b4841Sthorpej if (macbits > 0) {
1029468b4841Sthorpej CHAR(msgbuf, 0) = 0x00;
1030468b4841Sthorpej for (j = 0; j < macbits; j++)
1031468b4841Sthorpej CHAR(msgbuf, 0) |= (CHAR(msgbuf, n)&bits[j]);
1032468b4841Sthorpej (void)putchar(CHAR(msgbuf, 0));
1033468b4841Sthorpej }
1034468b4841Sthorpej }
1035468b4841Sthorpej
1036468b4841Sthorpej #ifndef FASTWAY
1037468b4841Sthorpej /*
1038468b4841Sthorpej * change from 8 bits/Uchar to 1 bit/Uchar
1039468b4841Sthorpej */
1040d9a44d71Sjoerg static void
expand(Desbuf from,char * to)104193bf7731Sthorpej expand(Desbuf from, char *to)
1042468b4841Sthorpej {
1043468b4841Sthorpej register int i, j; /* counters in for loop */
1044468b4841Sthorpej
1045468b4841Sthorpej for (i = 0; i < 8; i++)
1046468b4841Sthorpej for (j = 0; j < 8; j++)
1047468b4841Sthorpej *to++ = (CHAR(from, i)>>(7-j))&01;
1048468b4841Sthorpej }
1049468b4841Sthorpej
1050468b4841Sthorpej /*
1051468b4841Sthorpej * change from 1 bit/char to 8 bits/Uchar
1052468b4841Sthorpej */
1053d9a44d71Sjoerg static void
compress(char * from,Desbuf to)105493bf7731Sthorpej compress(char *from, Desbuf to)
1055468b4841Sthorpej {
1056468b4841Sthorpej register int i, j; /* counters in for loop */
1057468b4841Sthorpej
1058468b4841Sthorpej for (i = 0; i < 8; i++) {
1059468b4841Sthorpej CHAR(to, i) = 0;
1060468b4841Sthorpej for (j = 0; j < 8; j++)
1061468b4841Sthorpej CHAR(to, i) = ((*from++)<<(7-j))|CHAR(to, i);
1062468b4841Sthorpej }
1063468b4841Sthorpej }
1064468b4841Sthorpej #endif
1065468b4841Sthorpej
1066468b4841Sthorpej /*
1067468b4841Sthorpej * message about usage
1068468b4841Sthorpej */
1069d9a44d71Sjoerg static void
usage(void)107093bf7731Sthorpej usage(void)
1071468b4841Sthorpej {
107293bf7731Sthorpej
1073a8ec668dScgd (void) fprintf(stderr, "usage: %s %s\n", getprogname(),
107493bf7731Sthorpej "[-abdp] [-F bit] [-f bit] [-k key] [-m bit] [-o bit] [-v vector]");
1075468b4841Sthorpej exit(1);
1076468b4841Sthorpej }
1077