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