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.8 2005/01/11 13:22:40 joerg 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 <err.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 #include <openssl/bn.h> 57 #include <openssl/crypto.h> 58 #include <openssl/err.h> 59 60 static BIGNUM *modulus; 61 static char *fetchsecretkey( uid_t ); 62 static void writecache( char *, char *, des_block * ); 63 static int readcache( char *, char *, des_block * ); 64 static void extractdeskey ( BIGNUM *, des_block * ); 65 static int storesecretkey( uid_t, keybuf ); 66 static keystatus pk_crypt( uid_t, char *, netobj *, des_block *, int); 67 static int nodefaultkeys = 0; 68 69 70 /* 71 * prohibit the nobody key on this machine k (the -d flag) 72 */ 73 void 74 pk_nodefaultkeys(void) 75 { 76 nodefaultkeys = 1; 77 } 78 79 /* 80 * Set the modulus for all our Diffie-Hellman operations 81 */ 82 void 83 setmodulus(char *modx) 84 { 85 if (BN_hex2bn(&modulus, modx) == NULL) 86 errx(1, "could not convert modulus to BIGNUM: %s", 87 ERR_error_string(ERR_get_error(), 0)); 88 } 89 90 /* 91 * Set the secretkey key for this uid 92 */ 93 keystatus 94 pk_setkey(uid_t uid, keybuf skey) 95 { 96 if (!storesecretkey(uid, skey)) { 97 return (KEY_SYSTEMERR); 98 } 99 return (KEY_SUCCESS); 100 } 101 102 /* 103 * Encrypt the key using the public key associated with remote_name and the 104 * secret key associated with uid. 105 */ 106 keystatus 107 pk_encrypt(uid_t uid, char *remote_name, netobj *remote_key, 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_t uid, char *remote_name, netobj *remote_key, des_block *key) 118 { 119 return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT)); 120 } 121 122 static int store_netname( uid_t, key_netstarg * ); 123 static int fetch_netname( uid_t, key_netstarg * ); 124 125 keystatus 126 pk_netput(uid_t uid, key_netstarg *netstore) 127 { 128 if (!store_netname(uid, netstore)) { 129 return (KEY_SYSTEMERR); 130 } 131 return (KEY_SUCCESS); 132 } 133 134 keystatus 135 pk_netget(uid_t uid, key_netstarg *netstore) 136 { 137 if (!fetch_netname(uid, netstore)) { 138 return (KEY_SYSTEMERR); 139 } 140 return (KEY_SUCCESS); 141 } 142 143 144 /* 145 * Do the work of pk_encrypt && pk_decrypt 146 */ 147 static keystatus 148 pk_crypt(uid_t uid, char *remote_name, netobj *remote_key, des_block *key, 149 int mode) 150 { 151 char *xsecret; 152 char xpublic[1024]; 153 char xsecret_hold[1024]; 154 des_block deskey; 155 int error; 156 BIGNUM *public, *secret, *common; 157 BN_CTX *ctx; 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 if ((ctx = BN_CTX_new()) == NULL) 183 return (KEY_SYSTEMERR); 184 if (BN_hex2bn(&public, xpublic) == NULL) { 185 BN_CTX_free(ctx); 186 return (KEY_SYSTEMERR); 187 } 188 if (BN_hex2bn(&secret, xsecret) == NULL) { 189 BN_free(public); 190 BN_CTX_free(ctx); 191 return (KEY_SYSTEMERR); 192 } 193 194 if ((common = BN_new()) == NULL) { 195 BN_free(secret); 196 BN_free(public); 197 BN_CTX_free(ctx); 198 return (KEY_SYSTEMERR); 199 } 200 BN_zero(common); 201 BN_mod_exp(common, public, secret, modulus, ctx); 202 extractdeskey(common, &deskey); 203 writecache(xpublic, xsecret, &deskey); 204 BN_free(secret); 205 BN_free(public); 206 BN_free(common); 207 BN_CTX_free(ctx); 208 } 209 error = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block), 210 DES_HW | mode); 211 if (DES_FAILED(error)) { 212 return (KEY_SYSTEMERR); 213 } 214 return (KEY_SUCCESS); 215 } 216 217 keystatus 218 pk_get_conv_key(uid_t uid, keybuf xpublic, cryptkeyres *result) 219 { 220 char *xsecret; 221 char xsecret_hold[1024]; 222 BIGNUM *public, *secret, *common; 223 BN_CTX *ctx; 224 char zero[8]; 225 226 227 xsecret = fetchsecretkey(uid); 228 229 if (xsecret == NULL || xsecret[0] == 0) { 230 memset(zero, 0, sizeof (zero)); 231 xsecret = xsecret_hold; 232 if (nodefaultkeys) 233 return (KEY_NOSECRET); 234 235 if (!getsecretkey("nobody", xsecret, zero) || 236 xsecret[0] == 0) 237 return (KEY_NOSECRET); 238 } 239 240 if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey)) { 241 if ((ctx = BN_CTX_new()) == NULL) 242 return (KEY_SYSTEMERR); 243 if (BN_hex2bn(&public, xpublic) == NULL) { 244 BN_CTX_free(ctx); 245 return (KEY_SYSTEMERR); 246 } 247 if (BN_hex2bn(&secret, xsecret) == NULL) { 248 BN_free(public); 249 BN_CTX_free(ctx); 250 return (KEY_SYSTEMERR); 251 } 252 253 if ((common = BN_new()) == NULL) { 254 BN_free(secret); 255 BN_free(public); 256 BN_CTX_free(ctx); 257 return (KEY_SYSTEMERR); 258 } 259 BN_zero(common); 260 BN_mod_exp(common, public, secret, modulus, ctx); 261 262 extractdeskey(common, &result->cryptkeyres_u.deskey); 263 writecache(xpublic, xsecret, &result->cryptkeyres_u.deskey); 264 BN_free(secret); 265 BN_free(public); 266 BN_free(common); 267 BN_CTX_free(ctx); 268 } 269 270 return (KEY_SUCCESS); 271 } 272 273 /* 274 * Choose middle 64 bits of the common key to use as our des key, possibly 275 * overwriting the lower order bits by setting parity. 276 */ 277 static void 278 extractdeskey(BIGNUM *ck, des_block *deskey) 279 { 280 BIGNUM *a; 281 int i; 282 BN_ULONG r, base = (1 << 8); 283 char *k; 284 285 if ((a = BN_dup(ck)) == NULL) 286 errx(1, "could not copy BIGNUM"); 287 288 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 289 r = BN_div_word(a, base); 290 } 291 k = deskey->c; 292 for (i = 0; i < 8; i++) { 293 r = BN_div_word(a, base); 294 *k++ = r; 295 } 296 BN_free(a); 297 des_setparity((char *)deskey); 298 } 299 300 /* 301 * Key storage management 302 */ 303 304 #define KEY_ONLY 0 305 #define KEY_NAME 1 306 struct secretkey_netname_list { 307 uid_t uid; 308 key_netstarg keynetdata; 309 u_char sc_flag; 310 struct secretkey_netname_list *next; 311 }; 312 313 314 315 static struct secretkey_netname_list *g_secretkey_netname; 316 317 /* 318 * Store the keys and netname for this uid 319 */ 320 static int 321 store_netname(uid_t uid, 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 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_t uid, 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_t uid) 387 { 388 struct secretkey_netname_list *l; 389 390 for (l = g_secretkey_netname; l != NULL; l = l->next) { 391 if (l->uid == uid) { 392 return (l->keynetdata.st_priv_key); 393 } 394 } 395 return (NULL); 396 } 397 398 /* 399 * Store the secretkey for this uid 400 */ 401 static int 402 storesecretkey(uid_t uid, keybuf key) 403 { 404 struct secretkey_netname_list *new; 405 struct secretkey_netname_list **l; 406 407 for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid; 408 l = &(*l)->next) { 409 } 410 if (*l == NULL) { 411 new = (struct secretkey_netname_list *) malloc(sizeof (*new)); 412 if (new == NULL) { 413 return (0); 414 } 415 new->uid = uid; 416 new->sc_flag = KEY_ONLY; 417 memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 418 new->keynetdata.st_netname = NULL; 419 new->next = NULL; 420 *l = new; 421 } else { 422 new = *l; 423 } 424 425 memcpy(new->keynetdata.st_priv_key, key, 426 HEXKEYBYTES); 427 return (1); 428 } 429 430 static int 431 hexdigit(int val) 432 { 433 return ("0123456789abcdef"[val]); 434 } 435 436 void 437 bin2hex(unsigned char *bin, unsigned char *hex, int size) 438 { 439 int i; 440 441 for (i = 0; i < size; i++) { 442 *hex++ = hexdigit(*bin >> 4); 443 *hex++ = hexdigit(*bin++ & 0xf); 444 } 445 } 446 447 static int 448 hexval(char dig) 449 { 450 if ('0' <= dig && dig <= '9') { 451 return (dig - '0'); 452 } else if ('a' <= dig && dig <= 'f') { 453 return (dig - 'a' + 10); 454 } else if ('A' <= dig && dig <= 'F') { 455 return (dig - 'A' + 10); 456 } else { 457 return (-1); 458 } 459 } 460 461 void 462 hex2bin(unsigned char *hex, unsigned char *bin, int size) 463 { 464 int i; 465 466 for (i = 0; i < size; i++) { 467 *bin = hexval(*hex++) << 4; 468 *bin++ |= hexval(*hex++); 469 } 470 } 471 472 /* 473 * Exponential caching management 474 */ 475 struct cachekey_list { 476 keybuf secret; 477 keybuf public; 478 des_block deskey; 479 struct cachekey_list *next; 480 }; 481 static struct cachekey_list *g_cachedkeys; 482 483 /* 484 * cache result of expensive multiple precision exponential operation 485 */ 486 static void 487 writecache(char *pub, char *sec, des_block *deskey) 488 { 489 struct cachekey_list *new; 490 491 new = (struct cachekey_list *) malloc(sizeof (struct cachekey_list)); 492 if (new == NULL) { 493 return; 494 } 495 memcpy(new->public, pub, sizeof (keybuf)); 496 memcpy(new->secret, sec, sizeof (keybuf)); 497 new->deskey = *deskey; 498 new->next = g_cachedkeys; 499 g_cachedkeys = new; 500 } 501 502 /* 503 * Try to find the common key in the cache 504 */ 505 static int 506 readcache(char *pub, char *sec, des_block *deskey) 507 { 508 struct cachekey_list *found; 509 struct cachekey_list **l; 510 511 #define cachehit(pub, sec, list) \ 512 (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \ 513 memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 514 515 for (l = &g_cachedkeys; (*l) != NULL && !cachehit(pub, sec, *l); 516 l = &(*l)->next) 517 ; 518 if ((*l) == NULL) { 519 return (0); 520 } 521 found = *l; 522 (*l) = (*l)->next; 523 found->next = g_cachedkeys; 524 g_cachedkeys = found; 525 *deskey = found->deskey; 526 return (1); 527 } 528