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/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23/*	  All Rights Reserved  	*/
24
25
26/*
27 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28 * Use is subject to license terms.
29 */
30
31/*
32 *	A one-rotor machine designed along the lines of Enigma
33 *	but considerably trivialized.
34 */
35
36#define	ECHO 010
37#include <stdio.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <string.h>
41#include <crypt.h>
42#include <errno.h>
43
44#define	ROTORSZ 256
45#define	MASK 0377
46char	t1[ROTORSZ];
47char	t2[ROTORSZ];
48char	t3[ROTORSZ];
49
50static void
51setup(pw)
52char *pw;
53{
54	int ic, i, k, temp;
55	unsigned random;
56	char buf[13];
57	long seed;
58	char *ret;
59	int err;
60
61	(void) strncpy(buf, pw, 8);
62	buf[8] = buf[0];
63	buf[9] = buf[1];
64	errno = 0;
65	ret = des_crypt(buf, &buf[8]);
66	if (ret == NULL) {
67		err = errno;
68		(void) fprintf(stderr, "crypt: setup failed, unable to"
69		    " initialize rotors: %s\n", strerror(err));
70		exit(1);
71	}
72	(void) strncpy(buf, ret, 13);
73	seed = 123;
74	for (i = 0; i < 13; i++)
75		seed = seed*buf[i] + i;
76	for (i = 0; i < ROTORSZ; i++) {
77		t1[i] = i;
78		t3[i] = 0;
79	}
80	for (i = 0; i < ROTORSZ; i++) {
81		seed = 5*seed + buf[i%13];
82		random = seed % 65521;
83		k = ROTORSZ-1 - i;
84		ic = (random&MASK)%(k+1);
85		random >>= 8;
86		temp = t1[k];
87		t1[k] = t1[ic];
88		t1[ic] = temp;
89		if (t3[k] != 0) continue;
90		ic = (random&MASK) % k;
91		while (t3[ic] != 0) ic = (ic+1) % k;
92		t3[k] = ic;
93		t3[ic] = k;
94	}
95	for (i = 0; i < ROTORSZ; i++)
96		t2[t1[i]&MASK] = i;
97}
98
99int
100main(int argc, char **argv)
101{
102	extern int optind;
103	char *p1;
104	int i, n1, n2, nchar;
105	int c;
106	struct {
107		long offset;
108		unsigned int count;
109	} header;
110	int pflag = 0;
111	int kflag = 0;
112	char *buf;
113	char key[8];
114	char keyvar[] = "CrYpTkEy=XXXXXXXX";
115	char *s;
116
117	if (argc < 2) {
118		if ((buf = (char *)getpass("Enter key:")) == NULL) {
119			(void) fprintf(stderr, "Cannot open /dev/tty\n");
120			exit(1);
121		}
122		setup(buf);
123	} else {
124		while ((c = getopt(argc, argv, "pk")) != EOF)
125			switch (c) {
126			case 'p':
127			/* notify editor that exec has succeeded */
128				if (write(1, "y", 1) != 1)
129					exit(1);
130				if (read(0, key, 8) != 8)
131					exit(1);
132				setup(key);
133				pflag = 1;
134				break;
135			case 'k':
136				if ((s = getenv("CrYpTkEy")) == (char *)NULL) {
137					(void) fprintf(stderr,
138					    "CrYpTkEy not set.\n");
139					exit(1);
140				}
141				(void) strncpy(key, s, 8);
142				setup(key);
143				kflag = 1;
144				break;
145			case '?':
146				(void) fprintf(stderr,
147				    "usage: crypt [ -k ] [ key]\n");
148				exit(2);
149			}
150		if (pflag == 0 && kflag == 0) {
151			(void) strncpy(keyvar+9, argv[optind], 8);
152			(void) putenv(keyvar);
153			(void) execlp("crypt", "crypt", "-k", 0);
154		}
155	}
156	if (pflag)
157		for (;;) {
158			if ((nchar = read(0, (char *)&header, sizeof (header)))
159			    != sizeof (header))
160				exit(nchar);
161			n1 = (int)(header.offset&MASK);
162			n2 = (int)((header.offset >> 8) &MASK);
163			nchar = header.count;
164			buf = (char *)malloc(nchar);
165			p1 = buf;
166			if (read(0, buf, nchar) != nchar)
167				exit(1);
168			while (nchar--) {
169				*p1 = t2[(t3[(t1[(*p1 + n1)&MASK]+
170				    n2)&MASK] - n2)&MASK] - n1;
171				n1++;
172				if (n1 == ROTORSZ) {
173					n1 = 0;
174					n2++;
175					if (n2 == ROTORSZ) n2 = 0;
176				}
177				p1++;
178			}
179			nchar = header.count;
180			if (write(1, buf, nchar) != nchar)
181				exit(1);
182			free(buf);
183		}
184
185	n1 = 0;
186	n2 = 0;
187
188	while ((i = getchar()) >= 0) {
189		i = t2[(t3[(t1[(i+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
190		(void) putchar(i);
191		n1++;
192		if (n1 == ROTORSZ) {
193			n1 = 0;
194			n2++;
195			if (n2 == ROTORSZ) n2 = 0;
196		}
197	}
198	return (0);
199}
200