📄 setkey.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)setkey.c 2.2 88/08/10 4.0 RPCSRC; from Copyr 1988 Sun Micro";#endif/* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 *//* * Copyright (C) 1986, Sun Microsystems, Inc. *//* * Do the real work of the keyserver . * Store secret keys. Compute common keys, * and use them to decrypt and encrypt DES keys . * Cache the common keys, so the * expensive computation is avoided. */#include <stdio.h>#include <sys/file.h>#include <mp.h>#include <rpc/rpc.h>#include <rpc/key_prot.h>#include <des_crypt.h>#include <sys/errno.h>extern char *malloc();extern char ROOTKEY[];static MINT *MODULUS;static char *fetchsecretkey();static keystatus pk_crypt();/* * Set the modulus for all our Diffie-Hellman operations */setmodulus(modx) char *modx;{ MODULUS = xtom(modx);}/* * Set the secretkey key for this uid */keystatuspk_setkey(uid, skey) short uid; keybuf skey;{ if (!storesecretkey(uid, skey)) { return (KEY_SYSTEMERR); } return (KEY_SUCCESS);}/* * Encrypt the key using the public key associated with remote_name and the * secret key associated with uid. */keystatuspk_encrypt(uid, remote_name, key) short uid; char *remote_name; des_block *key;{ return (pk_crypt(uid, remote_name, key, DES_ENCRYPT));}/* * Decrypt the key using the public key associated with remote_name and the * secret key associated with uid. */keystatuspk_decrypt(uid, remote_name, key) short uid; char *remote_name; des_block *key;{ return (pk_crypt(uid, remote_name, key, DES_DECRYPT));}/* * Do the work of pk_encrypt && pk_decrypt */static keystatuspk_crypt(uid, remote_name, key, mode) short uid; char *remote_name; des_block *key; int mode;{ char *xsecret; char xpublic[HEXKEYBYTES + 1]; char xsecret_hold[HEXKEYBYTES + 1]; des_block deskey; int err; MINT *public; MINT *secret; MINT *common; char zero[8]; xsecret = fetchsecretkey(uid); if (xsecret == NULL) { bzero(zero, sizeof(zero)); xsecret = xsecret_hold; if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) { return (KEY_NOSECRET); } } if (!getpublickey(remote_name, xpublic) && !getpublickey("nobody", xpublic)) { return (KEY_UNKNOWN); } if (!readcache(xpublic, xsecret, &deskey)) { public = xtom(xpublic); secret = xtom(xsecret); common = itom(0); pow(public, secret, MODULUS, common); extractdeskey(common, &deskey); writecache(xpublic, xsecret, &deskey); mfree(secret); mfree(public); mfree(common); } err = ecb_crypt(&deskey, key, sizeof(des_block), DES_HW | mode); if (DES_FAILED(err)) { return (KEY_SYSTEMERR); } return (KEY_SUCCESS);}/* * Choose middle 64 bits of the common key to use as our des key, possibly * overwriting the lower order bits by setting parity. */staticextractdeskey(ck, deskey) MINT *ck; des_block *deskey;{ MINT *a; short r; int i; short base = (1 << 8); char *k; a = itom(0); move(ck, a); for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { sdiv(a, base, a, &r); } k = deskey->c; for (i = 0; i < 8; i++) { sdiv(a, base, a, &r); *k++ = r; } mfree(a); des_setparity(deskey);}/* * Key storage management */struct secretkey_list { short uid; char secretkey[HEXKEYBYTES+1]; struct secretkey_list *next;};static struct secretkey_list *g_secretkeys;/* * Fetch the secret key for this uid */static char *fetchsecretkey(uid) short uid;{ struct secretkey_list *l; for (l = g_secretkeys; l != NULL; l = l->next) { if (l->uid == uid) { return (l->secretkey); } } return (NULL);}/* * Store the secretkey for this uid */storesecretkey(uid, key) short uid; keybuf key;{ struct secretkey_list *new; struct secretkey_list **l; int nitems; nitems = 0; for (l = &g_secretkeys; *l != NULL && (*l)->uid != uid; l = &(*l)->next) { nitems++; } if (*l == NULL) { new = (struct secretkey_list *)malloc(sizeof(*new)); if (new == NULL) { return (0); } new->uid = uid; new->next = NULL; *l = new; } else { new = *l; } bcopy(key, new->secretkey, HEXKEYBYTES); new->secretkey[HEXKEYBYTES] = 0; seekitem(nitems); writeitem(uid, new->secretkey); return (1);}hexdigit(val) int val;{ return ("0123456789abcdef"[val]);}bin2hex(bin, hex, size) unsigned char *bin; unsigned char *hex; int size;{ int i; for (i = 0; i < size; i++) { *hex++ = hexdigit(*bin >> 4); *hex++ = hexdigit(*bin++ & 0xf); }}hexval(dig) char dig;{ if ('0' <= dig && dig <= '9') { return (dig - '0'); } else if ('a' <= dig && dig <= 'f') { return (dig - 'a' + 10); } else if ('A' <= dig && dig <= 'F') { return (dig - 'A' + 10); } else { return (-1); }}hex2bin(hex, bin, size) unsigned char *hex; unsigned char *bin; int size;{ int i; for (i = 0; i < size; i++) { *bin = hexval(*hex++) << 4; *bin++ |= hexval(*hex++); }}static char KEYSTORE[] = "/etc/keystore";FILE *kf;openstore(){ kf = fopen(KEYSTORE, "r+"); if (kf == NULL) { kf = fopen(KEYSTORE, "w+"); if (kf == NULL) { return (0); } } setbuf(kf, NULL); return (1);}static char rootkey[KEYBYTES];static int haverootkey;struct storedkey { short uid; char crypt[KEYBYTES];};readkeys(){ struct secretkey_list *node; struct secretkey_list **l; int uid; char secretkey[HEXKEYBYTES+1]; if (kf == NULL) { return; } l = &g_secretkeys; seekitem(0); while (readitem(&uid, secretkey)) { node = (struct secretkey_list *)malloc(sizeof(*node)); if (node == NULL) { return; } node->uid = uid; bcopy(secretkey, node->secretkey, HEXKEYBYTES + 1); node->next = NULL; *l = node; l = &node->next; }}writekeys(){ struct secretkey_list *k; seekitem(0); for (k = g_secretkeys; k != NULL; k = k->next) { writeitem(k->uid, k->secretkey); }}seekitem(item) int item;{ if (kf != NULL) { fseek(kf, item * sizeof(struct storedkey), 0); }}writeitem(uid, key) int uid; char *key;{ struct storedkey item; char rootkey_tmp[KEYBYTES]; int reencrypt; if (kf == NULL) { return (1); } if (uid == 0) { writerootkey(key); hex2bin(key, rootkey_tmp, KEYBYTES); reencrypt = (haverootkey && bcmp(rootkey, rootkey_tmp, KEYBYTES) != 0); bcopy(rootkey_tmp, rootkey, KEYBYTES); haverootkey = 1; if (reencrypt) { writekeys(); return (1); } } if (!haverootkey) { return (1); } item.uid = uid; hex2bin(key, item.crypt, KEYBYTES); ecb_crypt(rootkey, item.crypt, KEYBYTES, DES_ENCRYPT|DES_HW); return (fwrite(&item, sizeof(item), 1, kf) >= 0);}readitem(uidp, key) int *uidp; char *key;{ struct storedkey item; if (!haverootkey || kf == NULL) { return (0); } if (fread(&item, sizeof(item), 1, kf) != 1) { return (0); } *uidp = item.uid; ecb_crypt(rootkey, item.crypt, KEYBYTES, DES_DECRYPT|DES_HW); bin2hex(item.crypt, key, KEYBYTES); key[HEXKEYBYTES] = 0; return (1);} /* * Root users store their key in /etc/$ROOTKEY so * that they can auto reboot without having to be * around to type a password. Storing this in a file * is rather dubious: it should really be in the EEPROM * so it does not go over the net for diskless machines. */writerootkey(secret) char *secret;{ char newline = '\n'; int fd; fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0); if (fd < 0) { perror(ROOTKEY); } else { if (write(fd, secret, strlen(secret)) < 0 || write(fd, &newline, sizeof(newline)) < 0) { (void)fprintf(stderr, "%s: ", ROOTKEY); perror("write"); } close(fd); }}/* * Exponential caching management */struct cachekey_list { keybuf secret; keybuf public; des_block deskey; struct cachekey_list *next;};static struct cachekey_list *g_cachedkeys;/* * cache result of expensive multiple precision exponential operation */staticwritecache(pub, sec, deskey) char *pub; char *sec; des_block *deskey;{ struct cachekey_list *new; new = (struct cachekey_list *) malloc(sizeof(struct cachekey_list)); if (new == NULL) { return; } bcopy(pub, new->public, sizeof(keybuf)); bcopy(sec, new->secret, sizeof(keybuf)); new->deskey = *deskey; new->next = g_cachedkeys; g_cachedkeys = new;}/* * Try to find the common key in the cache */staticreadcache(pub, sec, deskey) char *pub; char *sec; des_block *deskey;{ struct cachekey_list *found; register struct cachekey_list **l;#define cachehit(pub, sec, list) \ (bcmp(pub, (list)->public, sizeof(keybuf)) == 0 && \ bcmp(sec, (list)->secret, sizeof(keybuf)) == 0) for (l = &g_cachedkeys; (*l) != NULL && !cachehit(pub, sec, *l); l = &(*l)->next); if ((*l) == NULL) { return (0); } found = *l; (*l) = (*l)->next; found->next = g_cachedkeys; g_cachedkeys = found; *deskey = found->deskey; return (1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -