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