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