#include "mt.h"
#include <stdlib.h>
#include <mp.h>
#include <rpc/key_prot.h>
#include <rpcsvc/nis_dhext.h>
#include <thread.h>
extern long random();
extern void _mp_move(MINT *, MINT *);
extern void des_setparity(char *);
static void adjust();
void __gen_dhkeys();
static MINT *MODULUS_192_0;
static mutex_t mod_192_0_lck = DEFAULTMUTEX;
static bool_t first_time = TRUE;
static char dl_gen_funcname[] = "__dl_gen_dhkeys";
static char dl_gen_common_funcname[] = "__dl_gen_common_dhkeys";
static void
getseed(seed, seedsize, pass)
char *seed;
int seedsize;
unsigned char *pass;
{
int i;
int rseed;
struct timeval tv;
(void) gettimeofday(&tv, (struct timezone *)NULL);
rseed = tv.tv_sec + tv.tv_usec;
for (i = 0; i < 8; i++) {
rseed ^= (rseed << 8) | pass[i];
}
(void) srandom(rseed);
for (i = 0; i < seedsize; i++) {
seed[i] = (random() & 0xff) ^ pass[i % 8];
}
}
static void
adjust(keyout, keyin)
char keyout[HEXKEYBYTES + 1];
char *keyin;
{
char *p;
char *s;
for (p = keyin; *p; p++)
;
for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
*s = *p;
}
while (s >= keyout) {
*s-- = '0';
}
}
void
__gen_dhkeys(public, secret, pass)
char *public;
char *secret;
char *pass;
{
int i;
#define BASEBITS (8 * sizeof (short) - 1)
#define BASE (1 << BASEBITS)
MINT *pk = mp_itom(0);
MINT *sk = mp_itom(0);
MINT *tmp;
MINT *base = mp_itom(BASE/2);
MINT *root = mp_itom(PROOT);
MINT *modulus = mp_xtom(HEXMODULUS);
unsigned short r;
unsigned short seed[KEYSIZE/BASEBITS + 1];
char *xkey;
tmp = mp_itom(2);
mp_mult(base, tmp, base);
mp_mfree(tmp);
getseed((char *)seed, (int)sizeof (seed), (uchar_t *)pass);
for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
r = seed[i] % ((unsigned short)BASE);
tmp = mp_itom(r);
mp_mult(sk, base, sk);
mp_madd(sk, tmp, sk);
mp_mfree(tmp);
}
tmp = mp_itom(0);
mp_mdiv(sk, modulus, tmp, sk);
mp_mfree(tmp);
mp_pow(root, sk, modulus, pk);
xkey = mp_mtox(sk);
(void) adjust(secret, xkey);
xkey = mp_mtox(pk);
(void) adjust(public, xkey);
mp_mfree(sk);
mp_mfree(base);
mp_mfree(pk);
mp_mfree(root);
mp_mfree(modulus);
}
int
__gen_dhkeys_g(char *pkey,
char *skey,
keylen_t keylen,
algtype_t algtype,
char *pass)
{
const int classic_des = keylen == 192 && algtype == 0;
if (! pkey || ! skey || ! pass)
return (0);
if (classic_des) {
__gen_dhkeys(pkey, skey, pass);
return (1);
} else {
int (*dlfp)();
if (dlfp = (int (*)())__nis_get_mechanism_symbol(keylen,
algtype,
dl_gen_funcname)) {
(*dlfp)(pkey, skey, pass);
return (1);
}
}
return (0);
}
int
__extractdeskey(ck, deskey)
MINT *ck;
des_block *deskey;
{
MINT *a;
short r;
int i;
short base = (1 << 8);
char *k;
a = mp_itom(0);
_mp_move(ck, a);
for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
mp_sdiv(a, base, a, &r);
}
k = deskey->c;
for (i = 0; i < 8; i++) {
mp_sdiv(a, base, a, &r);
*k++ = r;
}
mp_mfree(a);
des_setparity((char *)deskey);
return (0);
}
static void
setmodulus_192_0(void)
{
(void) mutex_lock(&mod_192_0_lck);
if (first_time) {
first_time = FALSE;
MODULUS_192_0 = mp_xtom(HEXMODULUS);
}
(void) mutex_unlock(&mod_192_0_lck);
}
int
__gen_common_dhkeys_g(char *xpublic,
char *xsecret,
keylen_t keylen,
algtype_t algtype,
des_block deskeys[],
keynum_t keynum)
{
const int classic_des = keylen == 192 && algtype == 0;
if (! xpublic || ! xsecret || ! deskeys)
return (0);
if (classic_des) {
MINT *common;
MINT *public;
MINT *secret;
setmodulus_192_0();
public = mp_xtom(xpublic);
secret = mp_xtom(xsecret);
common = mp_itom(0);
mp_pow(public, secret, MODULUS_192_0, common);
(void) __extractdeskey(common, &deskeys[0]);
return (1);
} else {
int (*dlfp)();
if (dlfp = (int (*)())__nis_get_mechanism_symbol(keylen,
algtype,
dl_gen_common_funcname)) {
(*dlfp)(xpublic, xsecret, deskeys, keynum);
return (1);
}
}
return (0);
}