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