crypt.c revision a59d1975cc18cdd7bd7bcc5ad6a5b2ed7e62b473
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* A one-rotor machine designed along the lines of Enigma
* but considerably trivialized.
*/
/* EXPORT DELETE START */
#define ECHO 010
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <crypt.h>
#include <errno.h>
#define ROTORSZ 256
#define MASK 0377
char t1[ROTORSZ];
char t2[ROTORSZ];
char t3[ROTORSZ];
static void
setup(pw)
char *pw;
{
int ic, i, k, temp;
unsigned random;
char buf[13];
long seed;
char *ret;
int err;
(void) strncpy(buf, pw, 8);
buf[8] = buf[0];
buf[9] = buf[1];
errno = 0;
ret = des_crypt(buf, &buf[8]);
if (ret == NULL) {
err = errno;
(void) fprintf(stderr, "crypt: setup failed, unable to"
" initialize rotors: %s\n", strerror(err));
exit(1);
}
(void) strncpy(buf, ret, 13);
seed = 123;
for (i = 0; i < 13; i++)
seed = seed*buf[i] + i;
for (i = 0; i < ROTORSZ; i++) {
t1[i] = i;
t3[i] = 0;
}
for (i = 0; i < ROTORSZ; i++) {
seed = 5*seed + buf[i%13];
random = seed % 65521;
k = ROTORSZ-1 - i;
ic = (random&MASK)%(k+1);
random >>= 8;
temp = t1[k];
t1[k] = t1[ic];
t1[ic] = temp;
if (t3[k] != 0) continue;
ic = (random&MASK) % k;
while (t3[ic] != 0) ic = (ic+1) % k;
t3[k] = ic;
t3[ic] = k;
}
for (i = 0; i < ROTORSZ; i++)
t2[t1[i]&MASK] = i;
}
/* EXPORT DELETE END */
int
main(int argc, char **argv)
{
/* EXPORT DELETE START */
extern int optind;
char *p1;
int i, n1, n2, nchar;
int c;
struct {
long offset;
unsigned int count;
} header;
int pflag = 0;
int kflag = 0;
char *buf;
char key[8];
char keyvar[] = "CrYpTkEy=XXXXXXXX";
char *s;
if (argc < 2) {
if ((buf = (char *)getpass("Enter key:")) == NULL) {
(void) fprintf(stderr, "Cannot open /dev/tty\n");
exit(1);
}
setup(buf);
} else {
while ((c = getopt(argc, argv, "pk")) != EOF)
switch (c) {
case 'p':
/* notify editor that exec has succeeded */
if (write(1, "y", 1) != 1)
exit(1);
if (read(0, key, 8) != 8)
exit(1);
setup(key);
pflag = 1;
break;
case 'k':
if ((s = getenv("CrYpTkEy")) == (char *)NULL) {
(void) fprintf(stderr,
"CrYpTkEy not set.\n");
exit(1);
}
(void) strncpy(key, s, 8);
setup(key);
kflag = 1;
break;
case '?':
(void) fprintf(stderr,
"usage: crypt [ -k ] [ key]\n");
exit(2);
}
if (pflag == 0 && kflag == 0) {
(void) strncpy(keyvar+9, argv[optind], 8);
(void) putenv(keyvar);
(void) execlp("crypt", "crypt", "-k", 0);
}
}
if (pflag)
for (;;) {
if ((nchar = read(0, (char *)&header, sizeof (header)))
!= sizeof (header))
exit(nchar);
n1 = (int)(header.offset&MASK);
n2 = (int)((header.offset >> 8) &MASK);
nchar = header.count;
buf = (char *)malloc(nchar);
p1 = buf;
if (read(0, buf, nchar) != nchar)
exit(1);
while (nchar--) {
*p1 = t2[(t3[(t1[(*p1 + n1)&MASK]+
n2)&MASK] - n2)&MASK] - n1;
n1++;
if (n1 == ROTORSZ) {
n1 = 0;
n2++;
if (n2 == ROTORSZ) n2 = 0;
}
p1++;
}
nchar = header.count;
if (write(1, buf, nchar) != nchar)
exit(1);
free(buf);
}
n1 = 0;
n2 = 0;
while ((i = getchar()) >= 0) {
i = t2[(t3[(t1[(i+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
(void) putchar(i);
n1++;
if (n1 == ROTORSZ) {
n1 = 0;
n2++;
if (n2 == ROTORSZ) n2 = 0;
}
}
return (0);
/* EXPORT DELETE END */
}