static char sccsid
[] = "@(#)setkey.c 2.2 88/08/10 4.0 RPCSRC; from Copyr 1988 Sun Micro";
* 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
* 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.
* 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 <rpc/key_prot.h>
static char *fetchsecretkey();
static keystatus
pk_crypt();
* Set the modulus for all our Diffie-Hellman operations
* Set the secretkey key for this uid
if (!storesecretkey(uid
, skey
)) {
* Encrypt the key using the public key associated with remote_name and the
* secret key associated with uid.
pk_encrypt(uid
, remote_name
, 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.
pk_decrypt(uid
, remote_name
, key
)
return (pk_crypt(uid
, remote_name
, key
, DES_DECRYPT
));
* Do the work of pk_encrypt && pk_decrypt
pk_crypt(uid
, remote_name
, key
, mode
)
char xpublic
[HEXKEYBYTES
+ 1];
char xsecret_hold
[HEXKEYBYTES
+ 1];
xsecret
= fetchsecretkey(uid
);
bzero(zero
, sizeof(zero
));
if (!getsecretkey("nobody", xsecret
, zero
) ||
if (!getpublickey(remote_name
, xpublic
) &&
!getpublickey("nobody", xpublic
)) {
if (!readcache(xpublic
, xsecret
, &deskey
)) {
pow(public, secret
, MODULUS
, common
);
extractdeskey(common
, &deskey
);
writecache(xpublic
, xsecret
, &deskey
);
err
= ecb_crypt(&deskey
, key
, sizeof(des_block
), DES_HW
| mode
);
* Choose middle 64 bits of the common key to use as our des key, possibly
* overwriting the lower order bits by setting parity.
extractdeskey(ck
, deskey
)
for (i
= 0; i
< ((KEYSIZE
- 64) / 2) / 8; i
++) {
for (i
= 0; i
< 8; i
++) {
char secretkey
[HEXKEYBYTES
+1];
struct secretkey_list
*next
;
static struct secretkey_list
*g_secretkeys
;
* Fetch the secret key for this uid
struct secretkey_list
*l
;
for (l
= g_secretkeys
; l
!= NULL
; l
= l
->next
) {
* Store the secretkey for this uid
struct secretkey_list
*new;
struct secretkey_list
**l
;
for (l
= &g_secretkeys
; *l
!= NULL
&& (*l
)->uid
!= uid
;
new = (struct secretkey_list
*)malloc(sizeof(*new));
bcopy(key
, new->secretkey
, HEXKEYBYTES
);
new->secretkey
[HEXKEYBYTES
] = 0;
writeitem(uid
, new->secretkey
);
return ("0123456789abcdef"[val
]);
for (i
= 0; i
< size
; i
++) {
*hex
++ = hexdigit(*bin
>> 4);
*hex
++ = hexdigit(*bin
++ & 0xf);
if ('0' <= dig
&& dig
<= '9') {
} else if ('a' <= dig
&& dig
<= 'f') {
} else if ('A' <= dig
&& dig
<= 'F') {
for (i
= 0; i
< size
; i
++) {
*bin
= hexval(*hex
++) << 4;
*bin
++ |= hexval(*hex
++);
static char KEYSTORE
[] = "/etc/keystore";
kf
= fopen(KEYSTORE
, "r+");
kf
= fopen(KEYSTORE
, "w+");
static char rootkey
[KEYBYTES
];
struct secretkey_list
*node
;
struct secretkey_list
**l
;
char secretkey
[HEXKEYBYTES
+1];
while (readitem(&uid
, secretkey
)) {
node
= (struct secretkey_list
*)malloc(sizeof(*node
));
bcopy(secretkey
, node
->secretkey
, HEXKEYBYTES
+ 1);
struct secretkey_list
*k
;
for (k
= g_secretkeys
; k
!= NULL
; k
= k
->next
) {
writeitem(k
->uid
, k
->secretkey
);
fseek(kf
, item
* sizeof(struct storedkey
), 0);
char rootkey_tmp
[KEYBYTES
];
hex2bin(key
, rootkey_tmp
, KEYBYTES
);
reencrypt
= (haverootkey
&&
bcmp(rootkey
, rootkey_tmp
, KEYBYTES
) != 0);
bcopy(rootkey_tmp
, rootkey
, KEYBYTES
);
hex2bin(key
, item
.crypt
, KEYBYTES
);
ecb_crypt(rootkey
, item
.crypt
, KEYBYTES
, DES_ENCRYPT
|DES_HW
);
return (fwrite(&item
, sizeof(item
), 1, kf
) >= 0);
if (!haverootkey
|| kf
== NULL
) {
if (fread(&item
, sizeof(item
), 1, kf
) != 1) {
ecb_crypt(rootkey
, item
.crypt
, KEYBYTES
, DES_DECRYPT
|DES_HW
);
bin2hex(item
.crypt
, key
, KEYBYTES
);
* 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.
fd
= open(ROOTKEY
, O_WRONLY
|O_TRUNC
|O_CREAT
, 0);
if (write(fd
, secret
, strlen(secret
)) < 0 ||
write(fd
, &newline
, sizeof(newline
)) < 0) {
(void)fprintf(stderr
, "%s: ", ROOTKEY
);
* Exponential caching management
struct cachekey_list
*next
;
static struct cachekey_list
*g_cachedkeys
;
* cache result of expensive multiple precision exponential operation
writecache(pub
, sec
, deskey
)
struct cachekey_list
*new;
new = (struct cachekey_list
*) malloc(sizeof(struct cachekey_list
));
bcopy(pub
, new->public, sizeof(keybuf
));
bcopy(sec
, new->secret
, sizeof(keybuf
));
new->next
= g_cachedkeys
;
* Try to find the common key in the cache
readcache(pub
, sec
, 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)
(*l
) != NULL
&& !cachehit(pub
, sec
, *l
);
found
->next
= g_cachedkeys
;