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() 76 { 77 nodefaultkeys = 1; 78 } 79 80 /* 81 * Set the modulus for all our Diffie-Hellman operations 82 */ 83 void 84 setmodulus(modx) 85 char *modx; 86 { 87 MODULUS = xtom(modx); 88 } 89 90 /* 91 * Set the secretkey key for this uid 92 */ 93 keystatus 94 pk_setkey(uid, skey) 95 uid_t uid; 96 keybuf skey; 97 { 98 if (!storesecretkey(uid, skey)) { 99 return (KEY_SYSTEMERR); 100 } 101 return (KEY_SUCCESS); 102 } 103 104 /* 105 * Encrypt the key using the public key associated with remote_name and the 106 * secret key associated with uid. 107 */ 108 keystatus 109 pk_encrypt(uid, remote_name, remote_key, key) 110 uid_t uid; 111 char *remote_name; 112 netobj *remote_key; 113 des_block *key; 114 { 115 return (pk_crypt(uid, remote_name, remote_key, key, DES_ENCRYPT)); 116 } 117 118 /* 119 * Decrypt the key using the public key associated with remote_name and the 120 * secret key associated with uid. 121 */ 122 keystatus 123 pk_decrypt(uid, remote_name, remote_key, key) 124 uid_t uid; 125 char *remote_name; 126 netobj *remote_key; 127 des_block *key; 128 { 129 return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT)); 130 } 131 132 static int store_netname( uid_t, key_netstarg * ); 133 static int fetch_netname( uid_t, key_netstarg * ); 134 135 keystatus 136 pk_netput(uid, netstore) 137 uid_t uid; 138 key_netstarg *netstore; 139 { 140 if (!store_netname(uid, netstore)) { 141 return (KEY_SYSTEMERR); 142 } 143 return (KEY_SUCCESS); 144 } 145 146 keystatus 147 pk_netget(uid, netstore) 148 uid_t uid; 149 key_netstarg *netstore; 150 { 151 if (!fetch_netname(uid, netstore)) { 152 return (KEY_SYSTEMERR); 153 } 154 return (KEY_SUCCESS); 155 } 156 157 158 /* 159 * Do the work of pk_encrypt && pk_decrypt 160 */ 161 static keystatus 162 pk_crypt(uid, remote_name, remote_key, key, mode) 163 uid_t uid; 164 char *remote_name; 165 netobj *remote_key; 166 des_block *key; 167 int mode; 168 { 169 char *xsecret; 170 char xpublic[1024]; 171 char xsecret_hold[1024]; 172 des_block deskey; 173 int err; 174 MINT *public; 175 MINT *secret; 176 MINT *common; 177 char zero[8]; 178 179 xsecret = fetchsecretkey(uid); 180 if (xsecret == NULL || xsecret[0] == 0) { 181 memset(zero, 0, sizeof (zero)); 182 xsecret = xsecret_hold; 183 if (nodefaultkeys) 184 return (KEY_NOSECRET); 185 186 if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) { 187 return (KEY_NOSECRET); 188 } 189 } 190 if (remote_key) { 191 memcpy(xpublic, remote_key->n_bytes, remote_key->n_len); 192 } else { 193 bzero((char *)&xpublic, sizeof(xpublic)); 194 if (!getpublickey(remote_name, xpublic)) { 195 if (nodefaultkeys || !getpublickey("nobody", xpublic)) 196 return (KEY_UNKNOWN); 197 } 198 } 199 200 if (!readcache(xpublic, xsecret, &deskey)) { 201 public = xtom(xpublic); 202 secret = xtom(xsecret); 203 /* Sanity Check on public and private keys */ 204 if ((public == NULL) || (secret == NULL)) 205 return (KEY_SYSTEMERR); 206 207 common = itom(0); 208 pow(public, secret, MODULUS, common); 209 extractdeskey(common, &deskey); 210 writecache(xpublic, xsecret, &deskey); 211 mfree(secret); 212 mfree(public); 213 mfree(common); 214 } 215 err = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block), 216 DES_HW | mode); 217 if (DES_FAILED(err)) { 218 return (KEY_SYSTEMERR); 219 } 220 return (KEY_SUCCESS); 221 } 222 223 keystatus 224 pk_get_conv_key(uid, xpublic, result) 225 uid_t uid; 226 keybuf xpublic; 227 cryptkeyres *result; 228 { 229 char *xsecret; 230 char xsecret_hold[1024]; 231 MINT *public; 232 MINT *secret; 233 MINT *common; 234 char zero[8]; 235 236 237 xsecret = fetchsecretkey(uid); 238 239 if (xsecret == NULL || xsecret[0] == 0) { 240 memset(zero, 0, sizeof (zero)); 241 xsecret = xsecret_hold; 242 if (nodefaultkeys) 243 return (KEY_NOSECRET); 244 245 if (!getsecretkey("nobody", xsecret, zero) || 246 xsecret[0] == 0) 247 return (KEY_NOSECRET); 248 } 249 250 if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey)) { 251 public = xtom(xpublic); 252 secret = xtom(xsecret); 253 /* Sanity Check on public and private keys */ 254 if ((public == NULL) || (secret == NULL)) 255 return (KEY_SYSTEMERR); 256 257 common = itom(0); 258 pow(public, secret, MODULUS, common); 259 extractdeskey(common, &result->cryptkeyres_u.deskey); 260 writecache(xpublic, xsecret, &result->cryptkeyres_u.deskey); 261 mfree(secret); 262 mfree(public); 263 mfree(common); 264 } 265 266 return (KEY_SUCCESS); 267 } 268 269 /* 270 * Choose middle 64 bits of the common key to use as our des key, possibly 271 * overwriting the lower order bits by setting parity. 272 */ 273 static void 274 extractdeskey(ck, deskey) 275 MINT *ck; 276 des_block *deskey; 277 { 278 MINT *a; 279 short r; 280 int i; 281 short base = (1 << 8); 282 char *k; 283 284 a = itom(0); 285 #ifdef SOLARIS_MP 286 _mp_move(ck, a); 287 #else 288 move(ck, a); 289 #endif 290 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 291 sdiv(a, base, a, &r); 292 } 293 k = deskey->c; 294 for (i = 0; i < 8; i++) { 295 sdiv(a, base, a, &r); 296 *k++ = r; 297 } 298 mfree(a); 299 des_setparity((char *)deskey); 300 } 301 302 /* 303 * Key storage management 304 */ 305 306 #define KEY_ONLY 0 307 #define KEY_NAME 1 308 struct secretkey_netname_list { 309 uid_t uid; 310 key_netstarg keynetdata; 311 u_char sc_flag; 312 struct secretkey_netname_list *next; 313 }; 314 315 316 317 static struct secretkey_netname_list *g_secretkey_netname; 318 319 /* 320 * Store the keys and netname for this uid 321 */ 322 static int 323 store_netname(uid, netstore) 324 uid_t uid; 325 key_netstarg *netstore; 326 { 327 struct secretkey_netname_list *new; 328 struct secretkey_netname_list **l; 329 330 for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid; 331 l = &(*l)->next) { 332 } 333 if (*l == NULL) { 334 new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 335 if (new == NULL) { 336 return (0); 337 } 338 new->uid = uid; 339 new->next = NULL; 340 *l = new; 341 } else { 342 new = *l; 343 if (new->keynetdata.st_netname) 344 (void) free (new->keynetdata.st_netname); 345 } 346 memcpy(new->keynetdata.st_priv_key, netstore->st_priv_key, 347 HEXKEYBYTES); 348 memcpy(new->keynetdata.st_pub_key, netstore->st_pub_key, HEXKEYBYTES); 349 350 if (netstore->st_netname) 351 new->keynetdata.st_netname = strdup(netstore->st_netname); 352 else 353 new->keynetdata.st_netname = (char *)NULL; 354 new->sc_flag = KEY_NAME; 355 return (1); 356 357 } 358 359 /* 360 * Fetch the keys and netname for this uid 361 */ 362 363 static int 364 fetch_netname(uid, key_netst) 365 uid_t uid; 366 struct key_netstarg *key_netst; 367 { 368 struct secretkey_netname_list *l; 369 370 for (l = g_secretkey_netname; l != NULL; l = l->next) { 371 if ((l->uid == uid) && (l->sc_flag == KEY_NAME)){ 372 373 memcpy(key_netst->st_priv_key, 374 l->keynetdata.st_priv_key, HEXKEYBYTES); 375 376 memcpy(key_netst->st_pub_key, 377 l->keynetdata.st_pub_key, HEXKEYBYTES); 378 379 if (l->keynetdata.st_netname) 380 key_netst->st_netname = 381 strdup(l->keynetdata.st_netname); 382 else 383 key_netst->st_netname = NULL; 384 return (1); 385 } 386 } 387 388 return (0); 389 } 390 391 static char * 392 fetchsecretkey(uid) 393 uid_t uid; 394 { 395 struct secretkey_netname_list *l; 396 397 for (l = g_secretkey_netname; l != NULL; l = l->next) { 398 if (l->uid == uid) { 399 return (l->keynetdata.st_priv_key); 400 } 401 } 402 return (NULL); 403 } 404 405 /* 406 * Store the secretkey for this uid 407 */ 408 static int 409 storesecretkey(uid, key) 410 uid_t uid; 411 keybuf key; 412 { 413 struct secretkey_netname_list *new; 414 struct secretkey_netname_list **l; 415 416 for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid; 417 l = &(*l)->next) { 418 } 419 if (*l == NULL) { 420 new = (struct secretkey_netname_list *) malloc(sizeof (*new)); 421 if (new == NULL) { 422 return (0); 423 } 424 new->uid = uid; 425 new->sc_flag = KEY_ONLY; 426 memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 427 new->keynetdata.st_netname = NULL; 428 new->next = NULL; 429 *l = new; 430 } else { 431 new = *l; 432 } 433 434 memcpy(new->keynetdata.st_priv_key, key, 435 HEXKEYBYTES); 436 return (1); 437 } 438 439 static int 440 hexdigit(val) 441 int val; 442 { 443 return ("0123456789abcdef"[val]); 444 } 445 446 void 447 bin2hex(bin, hex, size) 448 unsigned char *bin; 449 unsigned char *hex; 450 int size; 451 { 452 int i; 453 454 for (i = 0; i < size; i++) { 455 *hex++ = hexdigit(*bin >> 4); 456 *hex++ = hexdigit(*bin++ & 0xf); 457 } 458 } 459 460 static int 461 hexval(dig) 462 char dig; 463 { 464 if ('0' <= dig && dig <= '9') { 465 return (dig - '0'); 466 } else if ('a' <= dig && dig <= 'f') { 467 return (dig - 'a' + 10); 468 } else if ('A' <= dig && dig <= 'F') { 469 return (dig - 'A' + 10); 470 } else { 471 return (-1); 472 } 473 } 474 475 void 476 hex2bin(hex, bin, size) 477 unsigned char *hex; 478 unsigned char *bin; 479 int size; 480 { 481 int i; 482 483 for (i = 0; i < size; i++) { 484 *bin = hexval(*hex++) << 4; 485 *bin++ |= hexval(*hex++); 486 } 487 } 488 489 /* 490 * Exponential caching management 491 */ 492 struct cachekey_list { 493 keybuf secret; 494 keybuf public; 495 des_block deskey; 496 struct cachekey_list *next; 497 }; 498 static struct cachekey_list *g_cachedkeys; 499 500 /* 501 * cache result of expensive multiple precision exponential operation 502 */ 503 static void 504 writecache(pub, sec, deskey) 505 char *pub; 506 char *sec; 507 des_block *deskey; 508 { 509 struct cachekey_list *new; 510 511 new = (struct cachekey_list *) malloc(sizeof (struct cachekey_list)); 512 if (new == NULL) { 513 return; 514 } 515 memcpy(new->public, pub, sizeof (keybuf)); 516 memcpy(new->secret, sec, sizeof (keybuf)); 517 new->deskey = *deskey; 518 new->next = g_cachedkeys; 519 g_cachedkeys = new; 520 } 521 522 /* 523 * Try to find the common key in the cache 524 */ 525 static int 526 readcache(pub, sec, deskey) 527 char *pub; 528 char *sec; 529 des_block *deskey; 530 { 531 struct cachekey_list *found; 532 register struct cachekey_list **l; 533 534 #define cachehit(pub, sec, list) \ 535 (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \ 536 memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 537 538 for (l = &g_cachedkeys; (*l) != NULL && !cachehit(pub, sec, *l); 539 l = &(*l)->next) 540 ; 541 if ((*l) == NULL) { 542 return (0); 543 } 544 found = *l; 545 (*l) = (*l)->next; 546 found->next = g_cachedkeys; 547 g_cachedkeys = found; 548 *deskey = found->deskey; 549 return (1); 550 } 551