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