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