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