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