des.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Features:
* Hardware or software implementation
* Cipher Block Chaining (default) or Electronic Code Book (-b) modes
* A word about the key:
* The DES standard specifies that the low bit of each of the 8 bytes
* of the key is used for odd parity. We prompt the user for an 8
* byte ASCII key and add parity to the high bit and use the result
* as the key. The nature of parity is that given any 7 bits you can
* figure out what the missing bit should be, so it doesn't matter which
* bit is used for parity; the information (in the theoretical sense) is
* the same.
*/
#include <stdio.h>
#include <string.h>
#include <rpc/des_crypt.h>
#define DES_CBC 0
#define DES_ECB 1
char *cmdname; /* our command name */
struct des_info {
char *key; /* encryption key */
char *ivec; /* initialization vector: CBC mode only */
unsigned flags; /* direction, device flags */
unsigned mode; /* des mode: ecb or cbc */
} g_des;
void fencrypt(void);
void fdecrypt(void);
void usage(void);
static void putparity(char *p);
int
{
int dirset = 0; /* set if dir set */
int fflg = 0; /* suppress warning if H/W DES not available */
unsigned err;
argc--;
switch (argv[0][1]) {
case 'e': /* encrypt */
break;
case 'd': /* decrypt */
break;
case 'b': /* use Book mode */
break;
case 'f': /* force silent */
fflg++;
break;
case 's': /* use software DES */
break;
case 'k': /* key */
if (--argc == 0)
usage();
*key++ = '\0';
break;
default:
usage();
}
argv++;
argc--;
}
if (!dirset)
usage();
if (argc > 0) {
if (ifd < 0) {
exit(1);
}
argv++;
argc--;
}
if (argc > 0) {
if (ofd < 0) {
exit(1);
}
argv++;
argc--;
}
if (argc)
usage();
exit(1);
}
}
if (!fflg) {
cmdname);
}
}
cmdname);
exit(1);
}
switch (flags & DES_DIRMASK) {
case DES_ENCRYPT:
fencrypt();
break;
case DES_DECRYPT:
fdecrypt();
break;
}
return (0);
}
int
no_hwdevice(void)
{
char key[8];
char buf[8];
}
int
no_swdevice(void)
{
char key[8];
char buf[8];
int res;
}
void
{
static char ivec[8];
}
void
{
} else {
}
}
char buf[DES_MAXDATA];
/*
* Encrypt a file:
* Takes an arbitrary number of bytes of input and
* produces an encrypted output file which is always the
* the next multiple of 8 bytes bigger (e.g., 64 -> 72, 71 -> 72)
* The last byte, when decrypted, gives the number of actual data bytes
* in the last 8 bytes. Other bytes are filled with random values to
* make it hard to cryptanalize.
*/
void
fencrypt(void)
{
int n, k, j;
char *cp;
j = n;
while (n & 7) {
k = 8 - (n & 7);
break;
n += j;
}
k = n &~ 7;
if (k == 0)
break;
perror("write");
if (j <= 0)
break;
}
if (n >= 0) {
k = 7 - (n & 7);
for (j = 0; j < k; j++)
*cp++ = n & 7;
cp -= 8;
perror("write");
} else
perror("read");
}
/*
* Decrypt a file:
* Look at the last byte of the last 8 byte block decrypted
* to determine how many of the last 8 bytes to save.
* This also serves as a check to see if the decryption succeeded
* with a probability of (256-8)/256.
*/
void
fdecrypt(void)
{
int n, k, j;
j = n;
while (n & 7) {
k = 8 - (n & 7);
break;
n += j;
}
if (j <= 0)
break;
if (last8)
n -= 8;
perror("write");
}
if (n >= 0) {
|| n != 0
|| ((signed char)last8[7]) < 0
else if (((signed char)last8[7]) > 0)
} else
perror("read");
}
void
usage(void)
{
"Usage: %s -e [-b] [-f] [-k key] [ infile [ outfile ] ]\n",
cmdname);
" or: %s -d [-b] [-f] [-k key] [ infile [ outfile ] ]\n",
cmdname);
exit(2);
}
/*
* Table giving odd parity (in high bit) for ASCII characters
* program does not use des_setparity() (which puts parity
* in low bit) in order to maintain backward compatibility
*/
static unsigned char partab[128] = {
0x80, 0x01, 0x02, 0x83, 0x04, 0x85, 0x86, 0x07,
0x08, 0x89, 0x8a, 0x0b, 0x8c, 0x0d, 0x0e, 0x8f,
0x10, 0x91, 0x92, 0x13, 0x94, 0x15, 0x16, 0x97,
0x98, 0x19, 0x1a, 0x9b, 0x1c, 0x9d, 0x9e, 0x1f,
0x20, 0xa1, 0xa2, 0x23, 0xa4, 0x25, 0x26, 0xa7,
0xa8, 0x29, 0x2a, 0xab, 0x2c, 0xad, 0xae, 0x2f,
0xb0, 0x31, 0x32, 0xb3, 0x34, 0xb5, 0xb6, 0x37,
0x38, 0xb9, 0xba, 0x3b, 0xbc, 0x3d, 0x3e, 0xbf,
0x40, 0xc1, 0xc2, 0x43, 0xc4, 0x45, 0x46, 0xc7,
0xc8, 0x49, 0x4a, 0xcb, 0x4c, 0xcd, 0xce, 0x4f,
0xd0, 0x51, 0x52, 0xd3, 0x54, 0xd5, 0xd6, 0x57,
0x58, 0xd9, 0xda, 0x5b, 0xdc, 0x5d, 0x5e, 0xdf,
0xe0, 0x61, 0x62, 0xe3, 0x64, 0xe5, 0xe6, 0x67,
0x68, 0xe9, 0xea, 0x6b, 0xec, 0x6d, 0x6e, 0xef,
0x70, 0xf1, 0xf2, 0x73, 0xf4, 0x75, 0x76, 0xf7,
0xf8, 0x79, 0x7a, 0xfb, 0x7c, 0xfd, 0xfe, 0x7f,
};
/*
* Add odd parity to high bit of 8 byte key
*/
static void
putparity(char *p)
{
int i;
for (i = 0; i < 8; i++) {
*p = partab[*p & 0x7f];
p++;
}
}