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$");
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
71189092Sed        z = mp_itom(0);
72189092Sed        a = mp_itom(0);
73189092Sed        mp_madd(ck, z, a);
7449887Snsayer        for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
75189092Sed                mp_sdiv(a, base, a, &r);
7649887Snsayer        }
7749887Snsayer        k = (char *)ideakey;
7849887Snsayer        for (i = 0; i < 16; i++) {
79189092Sed                mp_sdiv(a, base, a, &r);
8049887Snsayer                *k++ = r;
8149887Snsayer        }
82189092Sed	mp_mfree(z);
83189092Sed        mp_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
100189092Sed        z = mp_itom(0);
101189092Sed        a = mp_itom(0);
102189092Sed        mp_madd(ck, z, a);
10349887Snsayer        for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
104189092Sed                mp_sdiv(a, base, a, &r);
10549887Snsayer        }
10649887Snsayer        k = (char *)deskey;
10749887Snsayer        for (i = 0; i < 8; i++) {
108189092Sed                mp_sdiv(a, base, a, &r);
10949887Snsayer                *k++ = r;
11049887Snsayer        }
111189092Sed	mp_mfree(z);
112189092Sed        mp_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;
124189092Sed	MINT *modulus = mp_xtom(HEXMODULUS);
12549887Snsayer
126189092Sed        public = mp_xtom(xpublic);
127189092Sed        secret = mp_xtom(xsecret);
128189092Sed        common = mp_itom(0);
129189092Sed        mp_pow(public, secret, modulus, common);
13049887Snsayer        extractdeskey(common, deskey);
13149887Snsayer        extractideakey(common, ideakey);
13249887Snsayer	des_set_odd_parity(deskey);
133189092Sed        mp_mfree(common);
134189092Sed        mp_mfree(secret);
135189092Sed        mp_mfree(public);
136189092Sed	mp_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
164189092Sed        MINT *pk = mp_itom(0);
165189092Sed        MINT *sk = mp_itom(0);
16649887Snsayer        MINT *tmp;
167305552Sdim        MINT *base = mp_itom((short)BASE);
168189092Sed        MINT *root = mp_itom(PROOT);
169189092Sed        MINT *modulus = mp_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;
177189092Sed                tmp = mp_itom(r);
178189092Sed                mp_mult(sk, base, sk);
179189092Sed                mp_madd(sk, tmp, sk);
180189092Sed                mp_mfree(tmp);
18149887Snsayer        }
182189092Sed        tmp = mp_itom(0);
183189092Sed        mp_mdiv(sk, modulus, tmp, sk);
184189092Sed        mp_mfree(tmp);
185189092Sed        mp_pow(root, sk, modulus, pk);
186189092Sed        xkey = mp_mtox(sk);
18749887Snsayer        adjust(secret, xkey);
188189092Sed        xkey = mp_mtox(pk);
18949887Snsayer        adjust(public, xkey);
190189092Sed        mp_mfree(sk);
191189092Sed        mp_mfree(base);
192189092Sed        mp_mfree(pk);
193189092Sed        mp_mfree(root);
194189092Sed        mp_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] > '9')
25349887Snsayer			n1 = in[op] - 'A' + 10;
25449887Snsayer		else
25549887Snsayer			n1 = in[op] - '0';
25649887Snsayer		if (in[op+1] > '9')
25749887Snsayer			n2 = in[op+1] - 'A' + 10;
25849887Snsayer		else
25949887Snsayer			n2 = in[op+1] - '0';
26049887Snsayer		buf[l] = n1*16 +n2;
26149887Snsayer	}
26249887Snsayer	des_key_sched(key, k);
26376711Speter	des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
26449887Snsayer	out[strlen(in)/2] = '\0';
26549887Snsayer}
266