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, MERCHANTABILITY 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 */ 32 33 /* 34 * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. 35 */ 36 37 /* 38 * Do the real work of the keyserver. 39 * Store secret keys. Compute common keys, 40 * and use them to decrypt and encrypt DES keys. 41 * Cache the common keys, so the expensive computation is avoided. 42 */ 43 #include <err.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <sys/types.h> 49 #include <rpc/rpc.h> 50 #include <rpc/key_prot.h> 51 #include <rpc/des_crypt.h> 52 #include <rpc/des.h> 53 #include <sys/errno.h> 54 #include "keyserv.h" 55 #include <openssl/bn.h> 56 #include <openssl/crypto.h> 57 #include <openssl/err.h> 58 59 static BIGNUM *modulus; 60 static char *fetchsecretkey( uid_t ); 61 static void writecache( char *, char *, des_block * ); 62 static int readcache( char *, char *, des_block * ); 63 static void extractdeskey ( BIGNUM *, des_block * ); 64 static int storesecretkey( uid_t, keybuf ); 65 static keystatus pk_crypt( uid_t, char *, netobj *, des_block *, int); 66 static int nodefaultkeys = 0; 67 68 69 /* 70 * prohibit the nobody key on this machine k (the -d flag) 71 */ 72 void 73 pk_nodefaultkeys(void) 74 { 75 nodefaultkeys = 1; 76 } 77 78 /* 79 * Set the modulus for all our Diffie-Hellman operations 80 */ 81 void 82 setmodulus(char *modx) 83 { 84 modulus = NULL; 85 if (BN_hex2bn(&modulus, modx) == 0) 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 public = NULL; 185 if (BN_hex2bn(&public, xpublic) == 0) { 186 BN_CTX_free(ctx); 187 return (KEY_SYSTEMERR); 188 } 189 secret = NULL; 190 if (BN_hex2bn(&secret, xsecret) == 0) { 191 BN_free(public); 192 BN_CTX_free(ctx); 193 return (KEY_SYSTEMERR); 194 } 195 196 if ((common = BN_new()) == NULL) { 197 BN_free(secret); 198 BN_free(public); 199 BN_CTX_free(ctx); 200 return (KEY_SYSTEMERR); 201 } 202 BN_zero(common); 203 BN_mod_exp(common, public, secret, modulus, ctx); 204 extractdeskey(common, &deskey); 205 writecache(xpublic, xsecret, &deskey); 206 BN_free(secret); 207 BN_free(public); 208 BN_free(common); 209 BN_CTX_free(ctx); 210 } 211 error = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block), 212 DES_HW | mode); 213 if (DES_FAILED(error)) { 214 return (KEY_SYSTEMERR); 215 } 216 return (KEY_SUCCESS); 217 } 218 219 keystatus 220 pk_get_conv_key(uid_t uid, keybuf xpublic, cryptkeyres *result) 221 { 222 char *xsecret; 223 char xsecret_hold[1024]; 224 BIGNUM *public, *secret, *common; 225 BN_CTX *ctx; 226 char zero[8]; 227 228 229 xsecret = fetchsecretkey(uid); 230 231 if (xsecret == NULL || xsecret[0] == 0) { 232 memset(zero, 0, sizeof (zero)); 233 xsecret = xsecret_hold; 234 if (nodefaultkeys) 235 return (KEY_NOSECRET); 236 237 if (!getsecretkey("nobody", xsecret, zero) || 238 xsecret[0] == 0) 239 return (KEY_NOSECRET); 240 } 241 242 if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey)) { 243 if ((ctx = BN_CTX_new()) == NULL) 244 return (KEY_SYSTEMERR); 245 public = NULL; 246 if (BN_hex2bn(&public, xpublic) == 0) { 247 BN_CTX_free(ctx); 248 return (KEY_SYSTEMERR); 249 } 250 secret = NULL; 251 if (BN_hex2bn(&secret, xsecret) == 0) { 252 BN_free(public); 253 BN_CTX_free(ctx); 254 return (KEY_SYSTEMERR); 255 } 256 257 if ((common = BN_new()) == NULL) { 258 BN_free(secret); 259 BN_free(public); 260 BN_CTX_free(ctx); 261 return (KEY_SYSTEMERR); 262 } 263 BN_zero(common); 264 BN_mod_exp(common, public, secret, modulus, ctx); 265 266 extractdeskey(common, &result->cryptkeyres_u.deskey); 267 writecache(xpublic, xsecret, &result->cryptkeyres_u.deskey); 268 BN_free(secret); 269 BN_free(public); 270 BN_free(common); 271 BN_CTX_free(ctx); 272 } 273 274 return (KEY_SUCCESS); 275 } 276 277 /* 278 * Choose middle 64 bits of the common key to use as our des key, possibly 279 * overwriting the lower order bits by setting parity. 280 */ 281 static void 282 extractdeskey(BIGNUM *ck, des_block *deskey) 283 { 284 BIGNUM *a; 285 int i; 286 BN_ULONG r, base = (1 << 8); 287 char *k; 288 289 if ((a = BN_dup(ck)) == NULL) 290 errx(1, "could not copy BIGNUM"); 291 292 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 293 r = BN_div_word(a, base); 294 } 295 k = deskey->c; 296 for (i = 0; i < 8; i++) { 297 r = BN_div_word(a, base); 298 *k++ = r; 299 } 300 BN_free(a); 301 des_setparity((char *)deskey); 302 } 303 304 /* 305 * Key storage management 306 */ 307 308 #define KEY_ONLY 0 309 #define KEY_NAME 1 310 struct secretkey_netname_list { 311 uid_t uid; 312 key_netstarg keynetdata; 313 u_char sc_flag; 314 struct secretkey_netname_list *next; 315 }; 316 317 318 319 static struct secretkey_netname_list *g_secretkey_netname; 320 321 /* 322 * Store the keys and netname for this uid 323 */ 324 static int 325 store_netname(uid_t uid, 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 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 = 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_t uid, struct key_netstarg *key_netst) 365 { 366 struct secretkey_netname_list *l; 367 368 for (l = g_secretkey_netname; l != NULL; l = l->next) { 369 if ((l->uid == uid) && (l->sc_flag == KEY_NAME)){ 370 371 memcpy(key_netst->st_priv_key, 372 l->keynetdata.st_priv_key, HEXKEYBYTES); 373 374 memcpy(key_netst->st_pub_key, 375 l->keynetdata.st_pub_key, HEXKEYBYTES); 376 377 if (l->keynetdata.st_netname) 378 key_netst->st_netname = 379 strdup(l->keynetdata.st_netname); 380 else 381 key_netst->st_netname = NULL; 382 return (1); 383 } 384 } 385 386 return (0); 387 } 388 389 static char * 390 fetchsecretkey(uid_t uid) 391 { 392 struct secretkey_netname_list *l; 393 394 for (l = g_secretkey_netname; l != NULL; l = l->next) { 395 if (l->uid == uid) { 396 return (l->keynetdata.st_priv_key); 397 } 398 } 399 return (NULL); 400 } 401 402 /* 403 * Store the secretkey for this uid 404 */ 405 static int 406 storesecretkey(uid_t uid, keybuf key) 407 { 408 struct secretkey_netname_list *new; 409 struct secretkey_netname_list **l; 410 411 for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid; 412 l = &(*l)->next) { 413 } 414 if (*l == NULL) { 415 new = (struct secretkey_netname_list *) malloc(sizeof (*new)); 416 if (new == NULL) { 417 return (0); 418 } 419 new->uid = uid; 420 new->sc_flag = KEY_ONLY; 421 memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 422 new->keynetdata.st_netname = NULL; 423 new->next = NULL; 424 *l = new; 425 } else { 426 new = *l; 427 } 428 429 memcpy(new->keynetdata.st_priv_key, key, 430 HEXKEYBYTES); 431 return (1); 432 } 433 434 static int 435 hexdigit(int val) 436 { 437 return ("0123456789abcdef"[val]); 438 } 439 440 void 441 bin2hex(unsigned char *bin, unsigned char *hex, int size) 442 { 443 int i; 444 445 for (i = 0; i < size; i++) { 446 *hex++ = hexdigit(*bin >> 4); 447 *hex++ = hexdigit(*bin++ & 0xf); 448 } 449 } 450 451 static int 452 hexval(char dig) 453 { 454 if ('0' <= dig && dig <= '9') { 455 return (dig - '0'); 456 } else if ('a' <= dig && dig <= 'f') { 457 return (dig - 'a' + 10); 458 } else if ('A' <= dig && dig <= 'F') { 459 return (dig - 'A' + 10); 460 } else { 461 return (-1); 462 } 463 } 464 465 void 466 hex2bin(unsigned char *hex, unsigned char *bin, int size) 467 { 468 int i; 469 470 for (i = 0; i < size; i++) { 471 *bin = hexval(*hex++) << 4; 472 *bin++ |= hexval(*hex++); 473 } 474 } 475 476 /* 477 * Exponential caching management 478 */ 479 struct cachekey_list { 480 keybuf secret; 481 keybuf public; 482 des_block deskey; 483 struct cachekey_list *next; 484 }; 485 static struct cachekey_list *g_cachedkeys; 486 487 /* 488 * cache result of expensive multiple precision exponential operation 489 */ 490 static void 491 writecache(char *pub, char *sec, des_block *deskey) 492 { 493 struct cachekey_list *new; 494 495 new = (struct cachekey_list *) malloc(sizeof (struct cachekey_list)); 496 if (new == NULL) { 497 return; 498 } 499 memcpy(new->public, pub, sizeof (keybuf)); 500 memcpy(new->secret, sec, sizeof (keybuf)); 501 new->deskey = *deskey; 502 new->next = g_cachedkeys; 503 g_cachedkeys = new; 504 } 505 506 /* 507 * Try to find the common key in the cache 508 */ 509 static int 510 readcache(char *pub, char *sec, des_block *deskey) 511 { 512 struct cachekey_list *found; 513 struct cachekey_list **l; 514 515 #define cachehit(pub, sec, list) \ 516 (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \ 517 memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 518 519 for (l = &g_cachedkeys; (*l) != NULL && !cachehit(pub, sec, *l); 520 l = &(*l)->next) 521 ; 522 if ((*l) == NULL) { 523 return (0); 524 } 525 found = *l; 526 (*l) = (*l)->next; 527 found->next = g_cachedkeys; 528 g_cachedkeys = found; 529 *deskey = found->deskey; 530 return (1); 531 } 532