1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate * DES encrypt/decrypt command
31*0Sstevel@tonic-gate * Features:
32*0Sstevel@tonic-gate * Hardware or software implementation
33*0Sstevel@tonic-gate * Cipher Block Chaining (default) or Electronic Code Book (-b) modes
34*0Sstevel@tonic-gate * A word about the key:
35*0Sstevel@tonic-gate * The DES standard specifies that the low bit of each of the 8 bytes
36*0Sstevel@tonic-gate * of the key is used for odd parity. We prompt the user for an 8
37*0Sstevel@tonic-gate * byte ASCII key and add parity to the high bit and use the result
38*0Sstevel@tonic-gate * as the key. The nature of parity is that given any 7 bits you can
39*0Sstevel@tonic-gate * figure out what the missing bit should be, so it doesn't matter which
40*0Sstevel@tonic-gate * bit is used for parity; the information (in the theoretical sense) is
41*0Sstevel@tonic-gate * the same.
42*0Sstevel@tonic-gate */
43*0Sstevel@tonic-gate #include <stdio.h>
44*0Sstevel@tonic-gate #include <string.h>
45*0Sstevel@tonic-gate #include <rpc/des_crypt.h>
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate #define DES_CBC 0
48*0Sstevel@tonic-gate #define DES_ECB 1
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate
51*0Sstevel@tonic-gate int ifd=0, ofd=1; /* input and output descriptors */
52*0Sstevel@tonic-gate char *cmdname; /* our command name */
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate struct des_info {
56*0Sstevel@tonic-gate char *key; /* encryption key */
57*0Sstevel@tonic-gate char *ivec; /* initialization vector: CBC mode only */
58*0Sstevel@tonic-gate unsigned flags; /* direction, device flags */
59*0Sstevel@tonic-gate unsigned mode; /* des mode: ecb or cbc */
60*0Sstevel@tonic-gate } g_des;
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate void des_setup(char *key, unsigned int mode, unsigned int flags);
64*0Sstevel@tonic-gate void fencrypt(void);
65*0Sstevel@tonic-gate void fdecrypt(void);
66*0Sstevel@tonic-gate void usage(void);
67*0Sstevel@tonic-gate static void putparity(char *p);
68*0Sstevel@tonic-gate int
main(int argc,char ** argv)69*0Sstevel@tonic-gate main(int argc, char **argv)
70*0Sstevel@tonic-gate {
71*0Sstevel@tonic-gate char *key = NULL, keybuf[8], *getpass();
72*0Sstevel@tonic-gate unsigned mode = DES_CBC;
73*0Sstevel@tonic-gate unsigned flags = DES_HW;
74*0Sstevel@tonic-gate int dirset = 0; /* set if dir set */
75*0Sstevel@tonic-gate int fflg = 0; /* suppress warning if H/W DES not available */
76*0Sstevel@tonic-gate unsigned err;
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gate cmdname = *argv++;
79*0Sstevel@tonic-gate argc--;
80*0Sstevel@tonic-gate while (argc > 0 && argv[0][0] == '-') {
81*0Sstevel@tonic-gate switch (argv[0][1]) {
82*0Sstevel@tonic-gate case 'e': /* encrypt */
83*0Sstevel@tonic-gate flags |= DES_ENCRYPT; dirset++;
84*0Sstevel@tonic-gate break;
85*0Sstevel@tonic-gate case 'd': /* decrypt */
86*0Sstevel@tonic-gate flags |= DES_DECRYPT; dirset++;
87*0Sstevel@tonic-gate break;
88*0Sstevel@tonic-gate case 'b': /* use Book mode */
89*0Sstevel@tonic-gate mode = DES_ECB;
90*0Sstevel@tonic-gate break;
91*0Sstevel@tonic-gate case 'f': /* force silent */
92*0Sstevel@tonic-gate fflg++;
93*0Sstevel@tonic-gate break;
94*0Sstevel@tonic-gate case 's': /* use software DES */
95*0Sstevel@tonic-gate flags |= DES_SW;
96*0Sstevel@tonic-gate break;
97*0Sstevel@tonic-gate case 'k': /* key */
98*0Sstevel@tonic-gate if (--argc == 0)
99*0Sstevel@tonic-gate usage();
100*0Sstevel@tonic-gate strncpy(keybuf, *++argv, 8);
101*0Sstevel@tonic-gate for (key = *argv; *key; )
102*0Sstevel@tonic-gate *key++ = '\0';
103*0Sstevel@tonic-gate key = keybuf;
104*0Sstevel@tonic-gate break;
105*0Sstevel@tonic-gate default:
106*0Sstevel@tonic-gate usage();
107*0Sstevel@tonic-gate }
108*0Sstevel@tonic-gate argv++;
109*0Sstevel@tonic-gate argc--;
110*0Sstevel@tonic-gate }
111*0Sstevel@tonic-gate if (!dirset)
112*0Sstevel@tonic-gate usage();
113*0Sstevel@tonic-gate if (argc > 0) {
114*0Sstevel@tonic-gate ifd = open(*argv, 0);
115*0Sstevel@tonic-gate if (ifd < 0) {
116*0Sstevel@tonic-gate perror(*argv);
117*0Sstevel@tonic-gate exit(1);
118*0Sstevel@tonic-gate }
119*0Sstevel@tonic-gate argv++;
120*0Sstevel@tonic-gate argc--;
121*0Sstevel@tonic-gate }
122*0Sstevel@tonic-gate if (argc > 0) {
123*0Sstevel@tonic-gate ofd = creat(*argv, 0666);
124*0Sstevel@tonic-gate if (ofd < 0) {
125*0Sstevel@tonic-gate perror(*argv);
126*0Sstevel@tonic-gate exit(1);
127*0Sstevel@tonic-gate }
128*0Sstevel@tonic-gate argv++;
129*0Sstevel@tonic-gate argc--;
130*0Sstevel@tonic-gate }
131*0Sstevel@tonic-gate if (argc)
132*0Sstevel@tonic-gate usage();
133*0Sstevel@tonic-gate if (key == NULL) {
134*0Sstevel@tonic-gate if ((key = getpass("Enter key: ")) == NULL) {
135*0Sstevel@tonic-gate fprintf(stderr, "%s: unable to get key\n", cmdname);
136*0Sstevel@tonic-gate exit(1);
137*0Sstevel@tonic-gate }
138*0Sstevel@tonic-gate strncpy(keybuf, key, 8);
139*0Sstevel@tonic-gate }
140*0Sstevel@tonic-gate if ((flags & DES_DEVMASK) == DES_HW && no_hwdevice()) {
141*0Sstevel@tonic-gate flags &= ~DES_DEVMASK; /* clear device bit */
142*0Sstevel@tonic-gate flags |= DES_SW; /* set device to software */
143*0Sstevel@tonic-gate if (!fflg) {
144*0Sstevel@tonic-gate fprintf(stderr, "%s: WARNING: using software DES algorithm\n",
145*0Sstevel@tonic-gate cmdname);
146*0Sstevel@tonic-gate }
147*0Sstevel@tonic-gate }
148*0Sstevel@tonic-gate if ((flags & DES_DEVMASK) == DES_SW && no_swdevice()) {
149*0Sstevel@tonic-gate fprintf(stderr, "%s: no software encryption available\n",
150*0Sstevel@tonic-gate cmdname);
151*0Sstevel@tonic-gate exit(1);
152*0Sstevel@tonic-gate }
153*0Sstevel@tonic-gate des_setup(key, mode, flags);
154*0Sstevel@tonic-gate switch (flags & DES_DIRMASK) {
155*0Sstevel@tonic-gate case DES_ENCRYPT:
156*0Sstevel@tonic-gate fencrypt();
157*0Sstevel@tonic-gate break;
158*0Sstevel@tonic-gate case DES_DECRYPT:
159*0Sstevel@tonic-gate fdecrypt();
160*0Sstevel@tonic-gate break;
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate return (0);
163*0Sstevel@tonic-gate }
164*0Sstevel@tonic-gate
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gate
167*0Sstevel@tonic-gate int
no_hwdevice(void)168*0Sstevel@tonic-gate no_hwdevice(void)
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate char key[8];
171*0Sstevel@tonic-gate char buf[8];
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gate return (ecb_crypt(key,buf,8,DES_ENCRYPT | DES_HW) != 0);
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate
176*0Sstevel@tonic-gate
177*0Sstevel@tonic-gate int
no_swdevice(void)178*0Sstevel@tonic-gate no_swdevice(void)
179*0Sstevel@tonic-gate {
180*0Sstevel@tonic-gate char key[8];
181*0Sstevel@tonic-gate char buf[8];
182*0Sstevel@tonic-gate int res;
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate return (ecb_crypt(key,buf,8,DES_ENCRYPT | DES_SW) != 0);
185*0Sstevel@tonic-gate }
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate
190*0Sstevel@tonic-gate void
des_setup(char * key,unsigned int mode,unsigned int flags)191*0Sstevel@tonic-gate des_setup(char *key, unsigned int mode, unsigned int flags)
192*0Sstevel@tonic-gate {
193*0Sstevel@tonic-gate static char ivec[8];
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate g_des.flags = flags;
196*0Sstevel@tonic-gate g_des.mode = mode;
197*0Sstevel@tonic-gate putparity(key);
198*0Sstevel@tonic-gate g_des.key = key;
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate memset(ivec, 0, 8);
201*0Sstevel@tonic-gate g_des.ivec = ivec;
202*0Sstevel@tonic-gate }
203*0Sstevel@tonic-gate
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate void
crypt(char * buf,unsigned int len)206*0Sstevel@tonic-gate crypt(char *buf, unsigned int len)
207*0Sstevel@tonic-gate {
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate if (g_des.mode == DES_ECB) {
210*0Sstevel@tonic-gate ecb_crypt(g_des.key, buf, len, g_des.flags);
211*0Sstevel@tonic-gate } else {
212*0Sstevel@tonic-gate cbc_crypt(g_des.key, buf, len, g_des.flags, g_des.ivec);
213*0Sstevel@tonic-gate }
214*0Sstevel@tonic-gate }
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate
217*0Sstevel@tonic-gate char buf[DES_MAXDATA];
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate /*
220*0Sstevel@tonic-gate * Encrypt a file:
221*0Sstevel@tonic-gate * Takes an arbitrary number of bytes of input and
222*0Sstevel@tonic-gate * produces an encrypted output file which is always the
223*0Sstevel@tonic-gate * the next multiple of 8 bytes bigger (e.g., 64 -> 72, 71 -> 72)
224*0Sstevel@tonic-gate * The last byte, when decrypted, gives the number of actual data bytes
225*0Sstevel@tonic-gate * in the last 8 bytes. Other bytes are filled with random values to
226*0Sstevel@tonic-gate * make it hard to cryptanalize.
227*0Sstevel@tonic-gate */
228*0Sstevel@tonic-gate void
fencrypt(void)229*0Sstevel@tonic-gate fencrypt(void)
230*0Sstevel@tonic-gate {
231*0Sstevel@tonic-gate int n, k, j;
232*0Sstevel@tonic-gate char *cp;
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gate while ((n = read(ifd, buf, sizeof buf)) > 0) {
235*0Sstevel@tonic-gate j = n;
236*0Sstevel@tonic-gate while (n & 7) {
237*0Sstevel@tonic-gate k = 8 - (n & 7);
238*0Sstevel@tonic-gate if ((j = read(ifd, buf+n, k)) <= 0)
239*0Sstevel@tonic-gate break;
240*0Sstevel@tonic-gate n += j;
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate k = n &~ 7;
243*0Sstevel@tonic-gate if (k == 0)
244*0Sstevel@tonic-gate break;
245*0Sstevel@tonic-gate crypt(buf, k);
246*0Sstevel@tonic-gate if (write(ofd, buf, k) != k)
247*0Sstevel@tonic-gate perror("write");
248*0Sstevel@tonic-gate if (j <= 0)
249*0Sstevel@tonic-gate break;
250*0Sstevel@tonic-gate }
251*0Sstevel@tonic-gate if (n >= 0) {
252*0Sstevel@tonic-gate cp = &buf[n];
253*0Sstevel@tonic-gate k = 7 - (n & 7);
254*0Sstevel@tonic-gate srand(getpid());
255*0Sstevel@tonic-gate for (j = 0; j < k; j++)
256*0Sstevel@tonic-gate *cp++ = rand();
257*0Sstevel@tonic-gate *cp++ = n & 7;
258*0Sstevel@tonic-gate cp -= 8;
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate crypt(cp, 8);
261*0Sstevel@tonic-gate if (write(ofd, cp, 8) != 8)
262*0Sstevel@tonic-gate perror("write");
263*0Sstevel@tonic-gate } else
264*0Sstevel@tonic-gate perror("read");
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gate
268*0Sstevel@tonic-gate
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gate /*
271*0Sstevel@tonic-gate * Decrypt a file:
272*0Sstevel@tonic-gate * Look at the last byte of the last 8 byte block decrypted
273*0Sstevel@tonic-gate * to determine how many of the last 8 bytes to save.
274*0Sstevel@tonic-gate * This also serves as a check to see if the decryption succeeded
275*0Sstevel@tonic-gate * with a probability of (256-8)/256.
276*0Sstevel@tonic-gate */
277*0Sstevel@tonic-gate void
fdecrypt(void)278*0Sstevel@tonic-gate fdecrypt(void)
279*0Sstevel@tonic-gate {
280*0Sstevel@tonic-gate char last8buf[8], *last8;
281*0Sstevel@tonic-gate int n, k, j;
282*0Sstevel@tonic-gate
283*0Sstevel@tonic-gate last8 = NULL;
284*0Sstevel@tonic-gate while ((n = read(ifd, buf, sizeof buf)) > 0) {
285*0Sstevel@tonic-gate j = n;
286*0Sstevel@tonic-gate while (n & 7) {
287*0Sstevel@tonic-gate k = 8 - (n & 7);
288*0Sstevel@tonic-gate if ((j = read(ifd, buf+n, k)) <= 0)
289*0Sstevel@tonic-gate break;
290*0Sstevel@tonic-gate n += j;
291*0Sstevel@tonic-gate }
292*0Sstevel@tonic-gate if (j <= 0)
293*0Sstevel@tonic-gate break;
294*0Sstevel@tonic-gate crypt(buf, n);
295*0Sstevel@tonic-gate if (last8)
296*0Sstevel@tonic-gate write(ofd, last8, 8);
297*0Sstevel@tonic-gate last8 = last8buf;
298*0Sstevel@tonic-gate n -= 8;
299*0Sstevel@tonic-gate memcpy(last8, buf+n, 8);
300*0Sstevel@tonic-gate if (n && write(ofd, buf, n) != n)
301*0Sstevel@tonic-gate perror("write");
302*0Sstevel@tonic-gate }
303*0Sstevel@tonic-gate if (n >= 0) {
304*0Sstevel@tonic-gate if (last8 == NULL
305*0Sstevel@tonic-gate || n != 0
306*0Sstevel@tonic-gate || ((signed char)last8[7]) < 0
307*0Sstevel@tonic-gate || last8[7] > 7)
308*0Sstevel@tonic-gate fprintf(stderr, "%s: decryption failed\n", cmdname);
309*0Sstevel@tonic-gate else if (((signed char)last8[7]) > 0)
310*0Sstevel@tonic-gate write(ofd, last8, last8[7]);
311*0Sstevel@tonic-gate } else
312*0Sstevel@tonic-gate perror("read");
313*0Sstevel@tonic-gate }
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate void
usage(void)317*0Sstevel@tonic-gate usage(void)
318*0Sstevel@tonic-gate {
319*0Sstevel@tonic-gate fprintf(stderr,
320*0Sstevel@tonic-gate "Usage: %s -e [-b] [-f] [-k key] [ infile [ outfile ] ]\n",
321*0Sstevel@tonic-gate cmdname);
322*0Sstevel@tonic-gate fprintf(stderr,
323*0Sstevel@tonic-gate " or: %s -d [-b] [-f] [-k key] [ infile [ outfile ] ]\n",
324*0Sstevel@tonic-gate cmdname);
325*0Sstevel@tonic-gate fprintf(stderr, "Use -e to encrypt, -d to decrypt\n");
326*0Sstevel@tonic-gate exit(2);
327*0Sstevel@tonic-gate }
328*0Sstevel@tonic-gate
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate
332*0Sstevel@tonic-gate /*
333*0Sstevel@tonic-gate * Table giving odd parity (in high bit) for ASCII characters
334*0Sstevel@tonic-gate * program does not use des_setparity() (which puts parity
335*0Sstevel@tonic-gate * in low bit) in order to maintain backward compatibility
336*0Sstevel@tonic-gate */
337*0Sstevel@tonic-gate static unsigned char partab[128] = {
338*0Sstevel@tonic-gate 0x80, 0x01, 0x02, 0x83, 0x04, 0x85, 0x86, 0x07,
339*0Sstevel@tonic-gate 0x08, 0x89, 0x8a, 0x0b, 0x8c, 0x0d, 0x0e, 0x8f,
340*0Sstevel@tonic-gate 0x10, 0x91, 0x92, 0x13, 0x94, 0x15, 0x16, 0x97,
341*0Sstevel@tonic-gate 0x98, 0x19, 0x1a, 0x9b, 0x1c, 0x9d, 0x9e, 0x1f,
342*0Sstevel@tonic-gate 0x20, 0xa1, 0xa2, 0x23, 0xa4, 0x25, 0x26, 0xa7,
343*0Sstevel@tonic-gate 0xa8, 0x29, 0x2a, 0xab, 0x2c, 0xad, 0xae, 0x2f,
344*0Sstevel@tonic-gate 0xb0, 0x31, 0x32, 0xb3, 0x34, 0xb5, 0xb6, 0x37,
345*0Sstevel@tonic-gate 0x38, 0xb9, 0xba, 0x3b, 0xbc, 0x3d, 0x3e, 0xbf,
346*0Sstevel@tonic-gate 0x40, 0xc1, 0xc2, 0x43, 0xc4, 0x45, 0x46, 0xc7,
347*0Sstevel@tonic-gate 0xc8, 0x49, 0x4a, 0xcb, 0x4c, 0xcd, 0xce, 0x4f,
348*0Sstevel@tonic-gate 0xd0, 0x51, 0x52, 0xd3, 0x54, 0xd5, 0xd6, 0x57,
349*0Sstevel@tonic-gate 0x58, 0xd9, 0xda, 0x5b, 0xdc, 0x5d, 0x5e, 0xdf,
350*0Sstevel@tonic-gate 0xe0, 0x61, 0x62, 0xe3, 0x64, 0xe5, 0xe6, 0x67,
351*0Sstevel@tonic-gate 0x68, 0xe9, 0xea, 0x6b, 0xec, 0x6d, 0x6e, 0xef,
352*0Sstevel@tonic-gate 0x70, 0xf1, 0xf2, 0x73, 0xf4, 0x75, 0x76, 0xf7,
353*0Sstevel@tonic-gate 0xf8, 0x79, 0x7a, 0xfb, 0x7c, 0xfd, 0xfe, 0x7f,
354*0Sstevel@tonic-gate };
355*0Sstevel@tonic-gate
356*0Sstevel@tonic-gate
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate /*
359*0Sstevel@tonic-gate * Add odd parity to high bit of 8 byte key
360*0Sstevel@tonic-gate */
361*0Sstevel@tonic-gate static void
putparity(char * p)362*0Sstevel@tonic-gate putparity(char *p)
363*0Sstevel@tonic-gate {
364*0Sstevel@tonic-gate int i;
365*0Sstevel@tonic-gate
366*0Sstevel@tonic-gate for (i = 0; i < 8; i++) {
367*0Sstevel@tonic-gate *p = partab[*p & 0x7f];
368*0Sstevel@tonic-gate p++;
369*0Sstevel@tonic-gate }
370*0Sstevel@tonic-gate }
371