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