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