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