pk.c revision 87139
185690Snsayer/*-
285690Snsayer * Copyright (c) 1991, 1993
385690Snsayer *      Dave Safford.  All rights reserved.
485690Snsayer *
585690Snsayer * Redistribution and use in source and binary forms, with or without
685690Snsayer * modification, are permitted provided that the following conditions
785690Snsayer * are met:
885690Snsayer * 1. Redistributions of source code must retain the above copyright
985690Snsayer *    notice, this list of conditions and the following disclaimer.
1085690Snsayer * 2. Redistributions in binary form must reproduce the above copyright
1185690Snsayer *    notice, this list of conditions and the following disclaimer in the
1285690Snsayer *    documentation and/or other materials provided with the distribution.
1385690Snsayer * 3. Neither the name of the University nor the names of its contributors
1485690Snsayer *    may be used to endorse or promote products derived from this software
1585690Snsayer *    without specific prior written permission.
1685690Snsayer *
1785690Snsayer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1885690Snsayer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1985690Snsayer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2085690Snsayer * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2185690Snsayer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2285690Snsayer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2385690Snsayer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2485690Snsayer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2585690Snsayer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2685690Snsayer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2785690Snsayer * SUCH DAMAGE.
2885690Snsayer *
2985690Snsayer */
3085690Snsayer
3187139Smarkm#include <sys/cdefs.h>
3287139Smarkm
3387139Smarkm__FBSDID("$FreeBSD: head/contrib/telnet/libtelnet/pk.c 87139 2001-11-30 21:06:38Z markm $");
3487139Smarkm
3549887Snsayer/* public key routines */
3649887Snsayer/* functions:
3749887Snsayer	genkeys(char *public, char *secret)
3849887Snsayer	common_key(char *secret, char *public, desData *deskey)
3949887Snsayer        pk_encode(char *in, *out, DesData *deskey);
4049887Snsayer        pk_decode(char *in, *out, DesData *deskey);
4149887Snsayer      where
4249887Snsayer	char public[HEXKEYBYTES + 1];
4349887Snsayer	char secret[HEXKEYBYTES + 1];
4449887Snsayer */
4549887Snsayer
4681965Smarkm#include <sys/time.h>
4781965Smarkm#include <openssl/des.h>
4881965Smarkm#include <fcntl.h>
4949887Snsayer#include <stdio.h>
5087139Smarkm#include <stdlib.h>
5149887Snsayer#include <string.h>
5287139Smarkm
5349887Snsayer#include "mp.h"
5449887Snsayer#include "pk.h"
5549887Snsayer
5681965Smarkmstatic void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
5781965Smarkm
5849887Snsayer/*
5949887Snsayer * Choose top 128 bits of the common key to use as our idea key.
6049887Snsayer */
6181965Smarkmstatic void
6281965Smarkmextractideakey(MINT *ck, IdeaData *ideakey)
6349887Snsayer{
6449887Snsayer        MINT *a;
6549887Snsayer        MINT *z;
6649887Snsayer        short r;
6749887Snsayer        int i;
6849887Snsayer        short base = (1 << 8);
6949887Snsayer        char *k;
7049887Snsayer
7149887Snsayer        z = itom(0);
7249887Snsayer        a = itom(0);
7349887Snsayer        madd(ck, z, a);
7449887Snsayer        for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
7549887Snsayer                sdiv(a, base, a, &r);
7649887Snsayer        }
7749887Snsayer        k = (char *)ideakey;
7849887Snsayer        for (i = 0; i < 16; i++) {
7949887Snsayer                sdiv(a, base, a, &r);
8049887Snsayer                *k++ = r;
8149887Snsayer        }
8249887Snsayer	mfree(z);
8349887Snsayer        mfree(a);
8449887Snsayer}
8549887Snsayer
8649887Snsayer/*
8749887Snsayer * Choose middle 64 bits of the common key to use as our des key, possibly
8849887Snsayer * overwriting the lower order bits by setting parity.
8949887Snsayer */
9081965Smarkmstatic void
9181965Smarkmextractdeskey(MINT *ck, DesData *deskey)
9249887Snsayer{
9349887Snsayer        MINT *a;
9449887Snsayer        MINT *z;
9549887Snsayer        short r;
9649887Snsayer        int i;
9749887Snsayer        short base = (1 << 8);
9849887Snsayer        char *k;
9949887Snsayer
10049887Snsayer        z = itom(0);
10149887Snsayer        a = itom(0);
10249887Snsayer        madd(ck, z, a);
10349887Snsayer        for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
10449887Snsayer                sdiv(a, base, a, &r);
10549887Snsayer        }
10649887Snsayer        k = (char *)deskey;
10749887Snsayer        for (i = 0; i < 8; i++) {
10849887Snsayer                sdiv(a, base, a, &r);
10949887Snsayer                *k++ = r;
11049887Snsayer        }
11149887Snsayer	mfree(z);
11249887Snsayer        mfree(a);
11349887Snsayer}
11449887Snsayer
11549887Snsayer/*
11649887Snsayer * get common key from my secret key and his public key
11749887Snsayer */
11881965Smarkmvoid
11981965Smarkmcommon_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
12049887Snsayer{
12149887Snsayer        MINT *public;
12249887Snsayer        MINT *secret;
12349887Snsayer        MINT *common;
12449887Snsayer	MINT *modulus = xtom(HEXMODULUS);
12549887Snsayer
12649887Snsayer        public = xtom(xpublic);
12749887Snsayer        secret = xtom(xsecret);
12849887Snsayer        common = itom(0);
12949887Snsayer        pow(public, secret, modulus, common);
13049887Snsayer        extractdeskey(common, deskey);
13149887Snsayer        extractideakey(common, ideakey);
13249887Snsayer	des_set_odd_parity(deskey);
13349887Snsayer        mfree(common);
13449887Snsayer        mfree(secret);
13549887Snsayer        mfree(public);
13649887Snsayer	mfree(modulus);
13749887Snsayer}
13849887Snsayer
13949887Snsayer/*
14049887Snsayer * Generate a seed
14149887Snsayer */
14287139Smarkmstatic void
14381965Smarkmgetseed(char *seed, int seedsize)
14449887Snsayer{
14576711Speter	int i;
14676711Speter
14776691Snsayer	srandomdev();
14876691Snsayer	for (i = 0; i < seedsize; i++) {
14976691Snsayer		seed[i] = random() & 0xff;
15076691Snsayer	}
15149887Snsayer}
15249887Snsayer
15349887Snsayer/*
15449887Snsayer * Generate a random public/secret key pair
15549887Snsayer */
15681965Smarkmvoid
15781965Smarkmgenkeys(char *public, char *secret)
15849887Snsayer{
15987139Smarkm        size_t i;
16049887Snsayer
16149887Snsayer#       define BASEBITS (8*sizeof(short) - 1)
16249887Snsayer#       define BASE (1 << BASEBITS)
16349887Snsayer
16449887Snsayer        MINT *pk = itom(0);
16549887Snsayer        MINT *sk = itom(0);
16649887Snsayer        MINT *tmp;
16749887Snsayer        MINT *base = itom(BASE);
16849887Snsayer        MINT *root = itom(PROOT);
16949887Snsayer        MINT *modulus = xtom(HEXMODULUS);
17049887Snsayer        short r;
17149887Snsayer        unsigned short seed[KEYSIZE/BASEBITS + 1];
17249887Snsayer        char *xkey;
17349887Snsayer
17449887Snsayer        getseed((char *)seed, sizeof(seed));
17549887Snsayer        for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
17649887Snsayer                r = seed[i] % BASE;
17749887Snsayer                tmp = itom(r);
17849887Snsayer                mult(sk, base, sk);
17949887Snsayer                madd(sk, tmp, sk);
18049887Snsayer                mfree(tmp);
18149887Snsayer        }
18249887Snsayer        tmp = itom(0);
18349887Snsayer        mdiv(sk, modulus, tmp, sk);
18449887Snsayer        mfree(tmp);
18549887Snsayer        pow(root, sk, modulus, pk);
18649887Snsayer        xkey = mtox(sk);
18749887Snsayer        adjust(secret, xkey);
18849887Snsayer        xkey = mtox(pk);
18949887Snsayer        adjust(public, xkey);
19049887Snsayer        mfree(sk);
19149887Snsayer        mfree(base);
19249887Snsayer        mfree(pk);
19349887Snsayer        mfree(root);
19449887Snsayer        mfree(modulus);
19549887Snsayer}
19649887Snsayer
19749887Snsayer/*
19849887Snsayer * Adjust the input key so that it is 0-filled on the left
19949887Snsayer */
20081965Smarkmstatic void
20181965Smarkmadjust(char keyout[HEXKEYBYTES+1], char *keyin)
20249887Snsayer{
20349887Snsayer        char *p;
20449887Snsayer        char *s;
20549887Snsayer
20649887Snsayer        for (p = keyin; *p; p++)
20749887Snsayer                ;
20849887Snsayer        for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
20949887Snsayer                *s = *p;
21049887Snsayer        }
21149887Snsayer        while (s >= keyout) {
21249887Snsayer                *s-- = '0';
21349887Snsayer        }
21449887Snsayer}
21549887Snsayer
21649887Snsayerstatic char hextab[17] = "0123456789ABCDEF";
21749887Snsayer
21849887Snsayer/* given a DES key, cbc encrypt and translate input to terminated hex */
21981965Smarkmvoid
22081965Smarkmpk_encode(char *in, char *out, DesData *key)
22149887Snsayer{
22249887Snsayer	char buf[256];
22349887Snsayer	DesData i;
22449887Snsayer	des_key_schedule k;
22549887Snsayer	int l,op,deslen;
22649887Snsayer
22749887Snsayer	memset(&i,0,sizeof(i));
22849887Snsayer	memset(buf,0,sizeof(buf));
22949887Snsayer	deslen = ((strlen(in) + 7)/8)*8;
23049887Snsayer	des_key_sched(key, k);
23176711Speter	des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT);
23249887Snsayer	for (l=0,op=0;l<deslen;l++) {
23349887Snsayer		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
23449887Snsayer		out[op++] = hextab[(buf[l] & 0x0f)];
23549887Snsayer	}
23649887Snsayer	out[op] = '\0';
23749887Snsayer}
23849887Snsayer
23949887Snsayer/* given a DES key, translate input from hex and decrypt */
24081965Smarkmvoid
24181965Smarkmpk_decode(char *in, char *out, DesData *key)
24249887Snsayer{
24349887Snsayer	char buf[256];
24449887Snsayer	DesData i;
24549887Snsayer	des_key_schedule k;
24687139Smarkm	int n1,n2,op;
24787139Smarkm	size_t l;
24849887Snsayer
24949887Snsayer	memset(&i,0,sizeof(i));
25049887Snsayer	memset(buf,0,sizeof(buf));
25149887Snsayer	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
25249887Snsayer		if(in[op] == '0' && in[op+1] == '0') {
25349887Snsayer			buf[l] = '\0';
25449887Snsayer			break;
25549887Snsayer		}
25649887Snsayer		if (in[op] > '9')
25749887Snsayer			n1 = in[op] - 'A' + 10;
25849887Snsayer		else
25949887Snsayer			n1 = in[op] - '0';
26049887Snsayer		if (in[op+1] > '9')
26149887Snsayer			n2 = in[op+1] - 'A' + 10;
26249887Snsayer		else
26349887Snsayer			n2 = in[op+1] - '0';
26449887Snsayer		buf[l] = n1*16 +n2;
26549887Snsayer	}
26649887Snsayer	des_key_sched(key, k);
26776711Speter	des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
26849887Snsayer	out[strlen(in)/2] = '\0';
26949887Snsayer}
270