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