1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 */ 29 30 #ifndef lint 31 #if 0 32 static char sccsid[] = "@(#)setkey.c 1.11 94/04/25 SMI"; 33 #endif 34 static const char rcsid[] = 35 "$FreeBSD$"; 36 #endif /* not lint */ 37 38 /* 39 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. 40 */ 41 42 /* 43 * Do the real work of the keyserver. 44 * Store secret keys. Compute common keys, 45 * and use them to decrypt and encrypt DES keys. 46 * Cache the common keys, so the expensive computation is avoided. 47 */ 48 #include <mp.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <unistd.h> 53 #include <sys/types.h> 54 #include <rpc/rpc.h> 55 #include <rpc/key_prot.h> 56 #include <rpc/des_crypt.h> 57 #include <rpc/des.h> 58 #include <sys/errno.h> 59 #include "keyserv.h" 60 61 static MINT *MODULUS; 62 static char *fetchsecretkey( uid_t ); 63 static void writecache( char *, char *, des_block * ); 64 static int readcache( char *, char *, des_block * ); 65 static void extractdeskey( MINT *, des_block * ); 66 static int storesecretkey( uid_t, keybuf ); 67 static keystatus pk_crypt( uid_t, char *, netobj *, des_block *, int); 68 static int nodefaultkeys = 0; 69 70 71 /* 72 * prohibit the nobody key on this machine k (the -d flag) 73 */ 74 void 75 pk_nodefaultkeys(void) 76 { 77 nodefaultkeys = 1; 78 } 79 80 /* 81 * Set the modulus for all our Diffie-Hellman operations 82 */ 83 void 84 setmodulus(char *modx) 85 { 86 MODULUS = mp_xtom(modx); 87 } 88 89 /* 90 * Set the secretkey key for this uid 91 */ 92 keystatus 93 pk_setkey(uid_t uid, keybuf skey) 94 { 95 if (!storesecretkey(uid, skey)) { 96 return (KEY_SYSTEMERR); 97 } 98 return (KEY_SUCCESS); 99 } 100 101 /* 102 * Encrypt the key using the public key associated with remote_name and the 103 * secret key associated with uid. 104 */ 105 keystatus 106 pk_encrypt(uid_t uid, char *remote_name, netobj *remote_key, des_block *key) 107 { 108 return (pk_crypt(uid, remote_name, remote_key, key, DES_ENCRYPT)); 109 } 110 111 /* 112 * Decrypt the key using the public key associated with remote_name and the 113 * secret key associated with uid. 114 */ 115 keystatus 116 pk_decrypt(uid_t uid, char *remote_name, netobj *remote_key, des_block *key) 117 { 118 return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT)); 119 } 120 121 static int store_netname( uid_t, key_netstarg * ); 122 static int fetch_netname( uid_t, key_netstarg * ); 123 124 keystatus 125 pk_netput(uid_t uid, key_netstarg *netstore) 126 { 127 if (!store_netname(uid, netstore)) { 128 return (KEY_SYSTEMERR); 129 } 130 return (KEY_SUCCESS); 131 } 132 133 keystatus 134 pk_netget(uid_t uid, key_netstarg *netstore) 135 { 136 if (!fetch_netname(uid, netstore)) { 137 return (KEY_SYSTEMERR); 138 } 139 return (KEY_SUCCESS); 140 } 141 142 143 /* 144 * Do the work of pk_encrypt && pk_decrypt 145 */ 146 static keystatus 147 pk_crypt(uid_t uid, char *remote_name, netobj *remote_key, des_block *key, 148 int mode) 149 { 150 char *xsecret; 151 char xpublic[1024]; 152 char xsecret_hold[1024]; 153 des_block deskey; 154 int err; 155 MINT *public; 156 MINT *secret; 157 MINT *common; 158 char zero[8]; 159 160 xsecret = fetchsecretkey(uid); 161 if (xsecret == NULL || xsecret[0] == 0) { 162 memset(zero, 0, sizeof (zero)); 163 xsecret = xsecret_hold; 164 if (nodefaultkeys) 165 return (KEY_NOSECRET); 166 167 if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) { 168 return (KEY_NOSECRET); 169 } 170 } 171 if (remote_key) { 172 memcpy(xpublic, remote_key->n_bytes, remote_key->n_len); 173 } else { 174 bzero((char *)&xpublic, sizeof(xpublic)); 175 if (!getpublickey(remote_name, xpublic)) { 176 if (nodefaultkeys || !getpublickey("nobody", xpublic)) 177 return (KEY_UNKNOWN); 178 } 179 } 180 181 if (!readcache(xpublic, xsecret, &deskey)) { 182 public = mp_xtom(xpublic); 183 secret = mp_xtom(xsecret); 184 /* Sanity Check on public and private keys */ 185 if ((public == NULL) || (secret == NULL)) 186 return (KEY_SYSTEMERR); 187 188 common = mp_itom(0); 189 mp_pow(public, secret, MODULUS, common); 190 extractdeskey(common, &deskey); 191 writecache(xpublic, xsecret, &deskey); 192 mp_mfree(secret); 193 mp_mfree(public); 194 mp_mfree(common); 195 } 196 err = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block), 197 DES_HW | mode); 198 if (DES_FAILED(err)) { 199 return (KEY_SYSTEMERR); 200 } 201 return (KEY_SUCCESS); 202 } 203 204 keystatus 205 pk_get_conv_key(uid_t uid, keybuf xpublic, cryptkeyres *result) 206 { 207 char *xsecret; 208 char xsecret_hold[1024]; 209 MINT *public; 210 MINT *secret; 211 MINT *common; 212 char zero[8]; 213 214 215 xsecret = fetchsecretkey(uid); 216 217 if (xsecret == NULL || xsecret[0] == 0) { 218 memset(zero, 0, sizeof (zero)); 219 xsecret = xsecret_hold; 220 if (nodefaultkeys) 221 return (KEY_NOSECRET); 222 223 if (!getsecretkey("nobody", xsecret, zero) || 224 xsecret[0] == 0) 225 return (KEY_NOSECRET); 226 } 227 228 if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey)) { 229 public = mp_xtom(xpublic); 230 secret = mp_xtom(xsecret); 231 /* Sanity Check on public and private keys */ 232 if ((public == NULL) || (secret == NULL)) 233 return (KEY_SYSTEMERR); 234 235 common = mp_itom(0); 236 mp_pow(public, secret, MODULUS, common); 237 extractdeskey(common, &result->cryptkeyres_u.deskey); 238 writecache(xpublic, xsecret, &result->cryptkeyres_u.deskey); 239 mp_mfree(secret); 240 mp_mfree(public); 241 mp_mfree(common); 242 } 243 244 return (KEY_SUCCESS); 245 } 246 247 /* 248 * Choose middle 64 bits of the common key to use as our des key, possibly 249 * overwriting the lower order bits by setting parity. 250 */ 251 static void 252 extractdeskey(MINT *ck, des_block *deskey) 253 { 254 MINT *a; 255 short r; 256 int i; 257 short base = (1 << 8); 258 char *k; 259 260 a = mp_itom(0); 261 #ifdef SOLARIS_MP 262 _mp_move(ck, a); 263 #else 264 mp_move(ck, a); 265 #endif 266 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 267 mp_sdiv(a, base, a, &r); 268 } 269 k = deskey->c; 270 for (i = 0; i < 8; i++) { 271 mp_sdiv(a, base, a, &r); 272 *k++ = r; 273 } 274 mp_mfree(a); 275 des_setparity((char *)deskey); 276 } 277 278 /* 279 * Key storage management 280 */ 281 282 #define KEY_ONLY 0 283 #define KEY_NAME 1 284 struct secretkey_netname_list { 285 uid_t uid; 286 key_netstarg keynetdata; 287 u_char sc_flag; 288 struct secretkey_netname_list *next; 289 }; 290 291 292 293 static struct secretkey_netname_list *g_secretkey_netname; 294 295 /* 296 * Store the keys and netname for this uid 297 */ 298 static int 299 store_netname(uid_t uid, key_netstarg *netstore) 300 { 301 struct secretkey_netname_list *new; 302 struct secretkey_netname_list **l; 303 304 for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid; 305 l = &(*l)->next) { 306 } 307 if (*l == NULL) { 308 new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 309 if (new == NULL) { 310 return (0); 311 } 312 new->uid = uid; 313 new->next = NULL; 314 *l = new; 315 } else { 316 new = *l; 317 if (new->keynetdata.st_netname) 318 (void) free (new->keynetdata.st_netname); 319 } 320 memcpy(new->keynetdata.st_priv_key, netstore->st_priv_key, 321 HEXKEYBYTES); 322 memcpy(new->keynetdata.st_pub_key, netstore->st_pub_key, HEXKEYBYTES); 323 324 if (netstore->st_netname) 325 new->keynetdata.st_netname = strdup(netstore->st_netname); 326 else 327 new->keynetdata.st_netname = (char *)NULL; 328 new->sc_flag = KEY_NAME; 329 return (1); 330 331 } 332 333 /* 334 * Fetch the keys and netname for this uid 335 */ 336 337 static int 338 fetch_netname(uid_t uid, struct key_netstarg *key_netst) 339 { 340 struct secretkey_netname_list *l; 341 342 for (l = g_secretkey_netname; l != NULL; l = l->next) { 343 if ((l->uid == uid) && (l->sc_flag == KEY_NAME)){ 344 345 memcpy(key_netst->st_priv_key, 346 l->keynetdata.st_priv_key, HEXKEYBYTES); 347 348 memcpy(key_netst->st_pub_key, 349 l->keynetdata.st_pub_key, HEXKEYBYTES); 350 351 if (l->keynetdata.st_netname) 352 key_netst->st_netname = 353 strdup(l->keynetdata.st_netname); 354 else 355 key_netst->st_netname = NULL; 356 return (1); 357 } 358 } 359 360 return (0); 361 } 362 363 static char * 364 fetchsecretkey(uid_t uid) 365 { 366 struct secretkey_netname_list *l; 367 368 for (l = g_secretkey_netname; l != NULL; l = l->next) { 369 if (l->uid == uid) { 370 return (l->keynetdata.st_priv_key); 371 } 372 } 373 return (NULL); 374 } 375 376 /* 377 * Store the secretkey for this uid 378 */ 379 static int 380 storesecretkey(uid_t uid, keybuf key) 381 { 382 struct secretkey_netname_list *new; 383 struct secretkey_netname_list **l; 384 385 for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid; 386 l = &(*l)->next) { 387 } 388 if (*l == NULL) { 389 new = (struct secretkey_netname_list *) malloc(sizeof (*new)); 390 if (new == NULL) { 391 return (0); 392 } 393 new->uid = uid; 394 new->sc_flag = KEY_ONLY; 395 memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 396 new->keynetdata.st_netname = NULL; 397 new->next = NULL; 398 *l = new; 399 } else { 400 new = *l; 401 } 402 403 memcpy(new->keynetdata.st_priv_key, key, 404 HEXKEYBYTES); 405 return (1); 406 } 407 408 static int 409 hexdigit(int val) 410 { 411 return ("0123456789abcdef"[val]); 412 } 413 414 void 415 bin2hex(unsigned char *bin, unsigned char *hex, int size) 416 { 417 int i; 418 419 for (i = 0; i < size; i++) { 420 *hex++ = hexdigit(*bin >> 4); 421 *hex++ = hexdigit(*bin++ & 0xf); 422 } 423 } 424 425 static int 426 hexval(char dig) 427 { 428 if ('0' <= dig && dig <= '9') { 429 return (dig - '0'); 430 } else if ('a' <= dig && dig <= 'f') { 431 return (dig - 'a' + 10); 432 } else if ('A' <= dig && dig <= 'F') { 433 return (dig - 'A' + 10); 434 } else { 435 return (-1); 436 } 437 } 438 439 void 440 hex2bin(unsigned char *hex, unsigned char *bin, int size) 441 { 442 int i; 443 444 for (i = 0; i < size; i++) { 445 *bin = hexval(*hex++) << 4; 446 *bin++ |= hexval(*hex++); 447 } 448 } 449 450 /* 451 * Exponential caching management 452 */ 453 struct cachekey_list { 454 keybuf secret; 455 keybuf public; 456 des_block deskey; 457 struct cachekey_list *next; 458 }; 459 static struct cachekey_list *g_cachedkeys; 460 461 /* 462 * cache result of expensive multiple precision exponential operation 463 */ 464 static void 465 writecache(char *pub, char *sec, des_block *deskey) 466 { 467 struct cachekey_list *new; 468 469 new = (struct cachekey_list *) malloc(sizeof (struct cachekey_list)); 470 if (new == NULL) { 471 return; 472 } 473 memcpy(new->public, pub, sizeof (keybuf)); 474 memcpy(new->secret, sec, sizeof (keybuf)); 475 new->deskey = *deskey; 476 new->next = g_cachedkeys; 477 g_cachedkeys = new; 478 } 479 480 /* 481 * Try to find the common key in the cache 482 */ 483 static int 484 readcache(char *pub, char *sec, des_block *deskey) 485 { 486 struct cachekey_list *found; 487 register struct cachekey_list **l; 488 489 #define cachehit(pub, sec, list) \ 490 (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \ 491 memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 492 493 for (l = &g_cachedkeys; (*l) != NULL && !cachehit(pub, sec, *l); 494 l = &(*l)->next) 495 ; 496 if ((*l) == NULL) { 497 return (0); 498 } 499 found = *l; 500 (*l) = (*l)->next; 501 found->next = g_cachedkeys; 502 g_cachedkeys = found; 503 *deskey = found->deskey; 504 return (1); 505 } 506