xref: /netbsd-src/lib/libskey/skeysubr.c (revision fdecd6a253f999ae92b139670d9e15cc9df4497c)
1 /*	$NetBSD: skeysubr.c,v 1.10 1997/06/28 01:12:19 christos Exp $	*/
2 
3 /* S/KEY v1.1b (skeysubr.c)
4  *
5  * Authors:
6  *          Neil M. Haller <nmh@thumper.bellcore.com>
7  *          Philip R. Karn <karn@chicago.qualcomm.com>
8  *          John S. Walden <jsw@thumper.bellcore.com>
9  *
10  * Modifications:
11  *          Scott Chasin <chasin@crimelab.com>
12  *
13  * S/KEY misc routines.
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <signal.h>
20 #include <termios.h>
21 #include <md4.h>
22 #include "skey.h"
23 
24 struct termios newtty;
25 struct termios oldtty;
26 
27 static void trapped __ARGS((int sig));
28 static void set_term __ARGS((void));
29 static void unset_term __ARGS((void));
30 static void echo_off __ARGS((void));
31 
32 /* Crunch a key:
33  * concatenate the seed and the password, run through MD4 and
34  * collapse to 64 bits. This is defined as the user's starting key.
35  */
36 int
37 keycrunch(result,seed,passwd)
38 char *result;	/* 8-byte result */
39 char *seed;	/* Seed, any length */
40 char *passwd;	/* Password, any length */
41 {
42 	char *buf;
43 	MD4_CTX md;
44 	unsigned int buflen;
45 	int i;
46 	register int tmp;
47 	u_int32_t hash[4];
48 
49 	buflen = strlen(seed) + strlen(passwd);
50 	if ((buf = (char *)malloc(buflen+1)) == NULL)
51 		return -1;
52 	strcpy(buf, seed);	/* XXX strcpy is safe */
53 	strcat(buf, passwd);	/* XXX strcat is safe */
54 
55 	/* Crunch the key through MD4 */
56 	sevenbit(buf);
57 	MD4Init(&md);
58 	MD4Update(&md, (unsigned char *) buf, buflen);
59 	MD4Final((unsigned char *) hash, &md);
60 
61 	free(buf);
62 
63 	/* Fold result from 128 to 64 bits */
64 	hash[0] ^= hash[2];
65 	hash[1] ^= hash[3];
66 
67 	/* Default (but slow) code that will convert to
68 	 * little-endian byte ordering on any machine
69 	 */
70 	for (i=0; i<2; i++) {
71 		tmp = hash[i];
72 		*result++ = tmp;
73 		tmp >>= 8;
74 		*result++ = tmp;
75 		tmp >>= 8;
76 		*result++ = tmp;
77 		tmp >>= 8;
78 		*result++ = tmp;
79 	}
80 
81 	return 0;
82 }
83 
84 /* The one-way function f(). Takes 8 bytes and returns 8 bytes in place */
85 void
86 f(x)
87 	char *x;
88 {
89 	MD4_CTX md;
90 	register int tmp;
91 	u_int32_t hash[4];
92 
93 	MD4Init(&md);
94 	MD4Update(&md, (unsigned char *) x, 8);
95 	MD4Final((unsigned char *) hash, &md);
96 
97 	/* Fold 128 to 64 bits */
98 	hash[0] ^= hash[2];
99 	hash[1] ^= hash[3];
100 
101 	/* Default (but slow) code that will convert to
102 	 * little-endian byte ordering on any machine
103 	 */
104 	tmp = hash[0];
105 	*x++ = tmp;
106 	tmp >>= 8;
107 	*x++ = tmp;
108 	tmp >>= 8;
109 	*x++ = tmp;
110 	tmp >>= 8;
111 	*x++ = tmp;
112 
113 	tmp = hash[1];
114 	*x++ = tmp;
115 	tmp >>= 8;
116 	*x++ = tmp;
117 	tmp >>= 8;
118 	*x++ = tmp;
119 	tmp >>= 8;
120 	*x = tmp;
121 }
122 
123 /* Strip trailing cr/lf from a line of text */
124 void
125 rip(buf)
126 	char *buf;
127 {
128 	char *cp;
129 
130 	if ((cp = strchr(buf,'\r')) != NULL)
131 		*cp = '\0';
132 
133 	if ((cp = strchr(buf,'\n')) != NULL)
134 		*cp = '\0';
135 }
136 
137 char *
138 readpass (buf,n)
139 	char *buf;
140 	int n;
141 {
142 	set_term();
143 	echo_off();
144 
145 	fgets(buf, n, stdin);
146 
147 	rip(buf);
148 	printf("\n");
149 
150 	sevenbit(buf);
151 
152 	unset_term();
153 	return buf;
154 }
155 
156 char *
157 readskey(buf, n)
158 	char *buf;
159 	int n;
160 {
161 	fgets (buf, n, stdin);
162 
163 	rip(buf);
164 	printf ("\n");
165 
166 	sevenbit (buf);
167 
168 	return buf;
169 }
170 
171 static void
172 set_term()
173 {
174 	fflush(stdout);
175 	tcgetattr(fileno(stdin), &newtty);
176 	tcgetattr(fileno(stdin), &oldtty);
177 
178 	signal (SIGINT, trapped);
179 }
180 
181 static void
182 echo_off()
183 {
184 	newtty.c_lflag &= ~(ICANON | ECHO | ECHONL);
185 	newtty.c_cc[VMIN] = 1;
186 	newtty.c_cc[VTIME] = 0;
187 	newtty.c_cc[VINTR] = 3;
188 
189 	tcsetattr(fileno(stdin), TCSADRAIN, &newtty);
190 }
191 
192 static void
193 unset_term()
194 {
195 	tcsetattr(fileno(stdin), TCSADRAIN, &oldtty);
196 }
197 
198 static void
199 trapped(sig)
200 	int sig;
201 {
202 	signal(SIGINT, trapped);
203 	printf("^C\n");
204 	unset_term();
205 	exit(-1);
206 }
207 
208 /* Convert 8-byte hex-ascii string to binary array
209  * Returns 0 on success, -1 on error
210  */
211 int
212 atob8(out, in)
213 	register char *out, *in;
214 {
215 	register int i;
216 	register int val;
217 
218 	if (in == NULL || out == NULL)
219 		return -1;
220 
221 	for (i=0; i<8; i++) {
222 		if ((in = skipspace(in)) == NULL)
223 			return -1;
224 		if ((val = htoi(*in++)) == -1)
225 			return -1;
226 		*out = val << 4;
227 
228 		if ((in = skipspace(in)) == NULL)
229 			return -1;
230 		if ((val = htoi(*in++)) == -1)
231 			return -1;
232 		*out++ |= val;
233 	}
234 	return 0;
235 }
236 
237 /* Convert 8-byte binary array to hex-ascii string */
238 int
239 btoa8(out, in)
240 	register char *out, *in;
241 {
242 	register int i;
243 
244 	if (in == NULL || out == NULL)
245 		return -1;
246 
247 	for (i=0;i<8;i++) {
248 		sprintf(out,"%02x",*in++ & 0xff);	/* XXX: sprintf() (btoa8() appears to be unused */
249 		out += 2;
250 	}
251 	return 0;
252 }
253 
254 
255 /* Convert hex digit to binary integer */
256 int
257 htoi(c)
258 	register char c;
259 {
260 	if ('0' <= c && c <= '9')
261 		return c - '0';
262 	if ('a' <= c && c <= 'f')
263 		return 10 + c - 'a';
264 	if ('A' <= c && c <= 'F')
265 		return 10 + c - 'A';
266 	return -1;
267 }
268 
269 char *
270 skipspace(cp)
271 	register char *cp;
272 {
273 	while (*cp == ' ' || *cp == '\t')
274 		cp++;
275 
276 	if (*cp == '\0')
277 		return NULL;
278 	else
279 		return cp;
280 }
281 
282 /* removebackspaced over charaters from the string */
283 void
284 backspace(buf)
285 char *buf;
286 {
287 	char bs = 0x8;
288 	char *cp = buf;
289 	char *out = buf;
290 
291 	while (*cp) {
292 		if (*cp == bs) {
293 			if (out == buf) {
294 				cp++;
295 				continue;
296 			}
297 			else {
298 			  cp++;
299 			  out--;
300 			}
301 		} else {
302 			*out++ = *cp++;
303 		}
304 
305 	}
306 	*out = '\0';
307 }
308 
309 /* sevenbit ()
310  *
311  * Make sure line is all seven bits.
312  */
313 
314 void
315 sevenbit(s)
316 	char *s;
317 {
318 	while (*s)
319 		*s++ &= 0x7f;
320 }
321