xref: /freebsd/contrib/telnet/libtelnet/pk.c (revision 8fa113e5fc65fe6abc757f0089f477a87ee4d185)
13737d6dfSNick Sayer /*-
23737d6dfSNick Sayer  * Copyright (c) 1991, 1993
33737d6dfSNick Sayer  *      Dave Safford.  All rights reserved.
43737d6dfSNick Sayer  *
53737d6dfSNick Sayer  * Redistribution and use in source and binary forms, with or without
63737d6dfSNick Sayer  * modification, are permitted provided that the following conditions
73737d6dfSNick Sayer  * are met:
83737d6dfSNick Sayer  * 1. Redistributions of source code must retain the above copyright
93737d6dfSNick Sayer  *    notice, this list of conditions and the following disclaimer.
103737d6dfSNick Sayer  * 2. Redistributions in binary form must reproduce the above copyright
113737d6dfSNick Sayer  *    notice, this list of conditions and the following disclaimer in the
123737d6dfSNick Sayer  *    documentation and/or other materials provided with the distribution.
133737d6dfSNick Sayer  * 3. Neither the name of the University nor the names of its contributors
143737d6dfSNick Sayer  *    may be used to endorse or promote products derived from this software
153737d6dfSNick Sayer  *    without specific prior written permission.
163737d6dfSNick Sayer  *
173737d6dfSNick Sayer  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
183737d6dfSNick Sayer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
193737d6dfSNick Sayer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
203737d6dfSNick Sayer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
213737d6dfSNick Sayer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
223737d6dfSNick Sayer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
233737d6dfSNick Sayer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
243737d6dfSNick Sayer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
253737d6dfSNick Sayer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
263737d6dfSNick Sayer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
273737d6dfSNick Sayer  * SUCH DAMAGE.
283737d6dfSNick Sayer  *
293737d6dfSNick Sayer  */
303737d6dfSNick Sayer 
318fa113e5SMark Murray #include <sys/cdefs.h>
328fa113e5SMark Murray 
338fa113e5SMark Murray __FBSDID("$FreeBSD$");
348fa113e5SMark Murray 
350f8c8396SNick Sayer /* public key routines */
360f8c8396SNick Sayer /* functions:
370f8c8396SNick Sayer 	genkeys(char *public, char *secret)
380f8c8396SNick Sayer 	common_key(char *secret, char *public, desData *deskey)
390f8c8396SNick Sayer         pk_encode(char *in, *out, DesData *deskey);
400f8c8396SNick Sayer         pk_decode(char *in, *out, DesData *deskey);
410f8c8396SNick Sayer       where
420f8c8396SNick Sayer 	char public[HEXKEYBYTES + 1];
430f8c8396SNick Sayer 	char secret[HEXKEYBYTES + 1];
440f8c8396SNick Sayer  */
450f8c8396SNick Sayer 
460f8c8396SNick Sayer #include <sys/time.h>
47bf4f84d4SMark Murray #include <openssl/des.h>
4821f083c0SMark Murray #include <fcntl.h>
4921f083c0SMark Murray #include <stdio.h>
508fa113e5SMark Murray #include <stdlib.h>
5121f083c0SMark Murray #include <string.h>
528fa113e5SMark Murray 
530f8c8396SNick Sayer #include "mp.h"
540f8c8396SNick Sayer #include "pk.h"
550f8c8396SNick Sayer 
5621f083c0SMark Murray static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
5721f083c0SMark Murray 
580f8c8396SNick Sayer /*
590f8c8396SNick Sayer  * Choose top 128 bits of the common key to use as our idea key.
600f8c8396SNick Sayer  */
6121f083c0SMark Murray static void
6221f083c0SMark Murray extractideakey(MINT *ck, IdeaData *ideakey)
630f8c8396SNick Sayer {
640f8c8396SNick Sayer         MINT *a;
650f8c8396SNick Sayer         MINT *z;
660f8c8396SNick Sayer         short r;
670f8c8396SNick Sayer         int i;
680f8c8396SNick Sayer         short base = (1 << 8);
690f8c8396SNick Sayer         char *k;
700f8c8396SNick Sayer 
710f8c8396SNick Sayer         z = itom(0);
720f8c8396SNick Sayer         a = itom(0);
730f8c8396SNick Sayer         madd(ck, z, a);
740f8c8396SNick Sayer         for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
750f8c8396SNick Sayer                 sdiv(a, base, a, &r);
760f8c8396SNick Sayer         }
770f8c8396SNick Sayer         k = (char *)ideakey;
780f8c8396SNick Sayer         for (i = 0; i < 16; i++) {
790f8c8396SNick Sayer                 sdiv(a, base, a, &r);
800f8c8396SNick Sayer                 *k++ = r;
810f8c8396SNick Sayer         }
820f8c8396SNick Sayer 	mfree(z);
830f8c8396SNick Sayer         mfree(a);
840f8c8396SNick Sayer }
850f8c8396SNick Sayer 
860f8c8396SNick Sayer /*
870f8c8396SNick Sayer  * Choose middle 64 bits of the common key to use as our des key, possibly
880f8c8396SNick Sayer  * overwriting the lower order bits by setting parity.
890f8c8396SNick Sayer  */
9021f083c0SMark Murray static void
9121f083c0SMark Murray extractdeskey(MINT *ck, DesData *deskey)
920f8c8396SNick Sayer {
930f8c8396SNick Sayer         MINT *a;
940f8c8396SNick Sayer         MINT *z;
950f8c8396SNick Sayer         short r;
960f8c8396SNick Sayer         int i;
970f8c8396SNick Sayer         short base = (1 << 8);
980f8c8396SNick Sayer         char *k;
990f8c8396SNick Sayer 
1000f8c8396SNick Sayer         z = itom(0);
1010f8c8396SNick Sayer         a = itom(0);
1020f8c8396SNick Sayer         madd(ck, z, a);
1030f8c8396SNick Sayer         for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
1040f8c8396SNick Sayer                 sdiv(a, base, a, &r);
1050f8c8396SNick Sayer         }
1060f8c8396SNick Sayer         k = (char *)deskey;
1070f8c8396SNick Sayer         for (i = 0; i < 8; i++) {
1080f8c8396SNick Sayer                 sdiv(a, base, a, &r);
1090f8c8396SNick Sayer                 *k++ = r;
1100f8c8396SNick Sayer         }
1110f8c8396SNick Sayer 	mfree(z);
1120f8c8396SNick Sayer         mfree(a);
1130f8c8396SNick Sayer }
1140f8c8396SNick Sayer 
1150f8c8396SNick Sayer /*
1160f8c8396SNick Sayer  * get common key from my secret key and his public key
1170f8c8396SNick Sayer  */
11821f083c0SMark Murray void
11921f083c0SMark Murray common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
1200f8c8396SNick Sayer {
1210f8c8396SNick Sayer         MINT *public;
1220f8c8396SNick Sayer         MINT *secret;
1230f8c8396SNick Sayer         MINT *common;
1240f8c8396SNick Sayer 	MINT *modulus = xtom(HEXMODULUS);
1250f8c8396SNick Sayer 
1260f8c8396SNick Sayer         public = xtom(xpublic);
1270f8c8396SNick Sayer         secret = xtom(xsecret);
1280f8c8396SNick Sayer         common = itom(0);
1290f8c8396SNick Sayer         pow(public, secret, modulus, common);
1300f8c8396SNick Sayer         extractdeskey(common, deskey);
1310f8c8396SNick Sayer         extractideakey(common, ideakey);
1320f8c8396SNick Sayer 	des_set_odd_parity(deskey);
1330f8c8396SNick Sayer         mfree(common);
1340f8c8396SNick Sayer         mfree(secret);
1350f8c8396SNick Sayer         mfree(public);
1360f8c8396SNick Sayer 	mfree(modulus);
1370f8c8396SNick Sayer }
1380f8c8396SNick Sayer 
1390f8c8396SNick Sayer /*
1400f8c8396SNick Sayer  * Generate a seed
1410f8c8396SNick Sayer  */
1428fa113e5SMark Murray static void
14321f083c0SMark Murray getseed(char *seed, int seedsize)
1440f8c8396SNick Sayer {
145d48d5be0SPeter Wemm 	int i;
146d48d5be0SPeter Wemm 
1478183ac8fSNick Sayer 	srandomdev();
1488183ac8fSNick Sayer 	for (i = 0; i < seedsize; i++) {
1498183ac8fSNick Sayer 		seed[i] = random() & 0xff;
1508183ac8fSNick Sayer 	}
1510f8c8396SNick Sayer }
1520f8c8396SNick Sayer 
1530f8c8396SNick Sayer /*
1540f8c8396SNick Sayer  * Generate a random public/secret key pair
1550f8c8396SNick Sayer  */
15621f083c0SMark Murray void
15721f083c0SMark Murray genkeys(char *public, char *secret)
1580f8c8396SNick Sayer {
1598fa113e5SMark Murray         size_t i;
1600f8c8396SNick Sayer 
1610f8c8396SNick Sayer #       define BASEBITS (8*sizeof(short) - 1)
1620f8c8396SNick Sayer #       define BASE (1 << BASEBITS)
1630f8c8396SNick Sayer 
1640f8c8396SNick Sayer         MINT *pk = itom(0);
1650f8c8396SNick Sayer         MINT *sk = itom(0);
1660f8c8396SNick Sayer         MINT *tmp;
1670f8c8396SNick Sayer         MINT *base = itom(BASE);
1680f8c8396SNick Sayer         MINT *root = itom(PROOT);
1690f8c8396SNick Sayer         MINT *modulus = xtom(HEXMODULUS);
1700f8c8396SNick Sayer         short r;
1710f8c8396SNick Sayer         unsigned short seed[KEYSIZE/BASEBITS + 1];
1720f8c8396SNick Sayer         char *xkey;
1730f8c8396SNick Sayer 
1740f8c8396SNick Sayer         getseed((char *)seed, sizeof(seed));
1750f8c8396SNick Sayer         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
1760f8c8396SNick Sayer                 r = seed[i] % BASE;
1770f8c8396SNick Sayer                 tmp = itom(r);
1780f8c8396SNick Sayer                 mult(sk, base, sk);
1790f8c8396SNick Sayer                 madd(sk, tmp, sk);
1800f8c8396SNick Sayer                 mfree(tmp);
1810f8c8396SNick Sayer         }
1820f8c8396SNick Sayer         tmp = itom(0);
1830f8c8396SNick Sayer         mdiv(sk, modulus, tmp, sk);
1840f8c8396SNick Sayer         mfree(tmp);
1850f8c8396SNick Sayer         pow(root, sk, modulus, pk);
1860f8c8396SNick Sayer         xkey = mtox(sk);
1870f8c8396SNick Sayer         adjust(secret, xkey);
1880f8c8396SNick Sayer         xkey = mtox(pk);
1890f8c8396SNick Sayer         adjust(public, xkey);
1900f8c8396SNick Sayer         mfree(sk);
1910f8c8396SNick Sayer         mfree(base);
1920f8c8396SNick Sayer         mfree(pk);
1930f8c8396SNick Sayer         mfree(root);
1940f8c8396SNick Sayer         mfree(modulus);
1950f8c8396SNick Sayer }
1960f8c8396SNick Sayer 
1970f8c8396SNick Sayer /*
1980f8c8396SNick Sayer  * Adjust the input key so that it is 0-filled on the left
1990f8c8396SNick Sayer  */
20021f083c0SMark Murray static void
20121f083c0SMark Murray adjust(char keyout[HEXKEYBYTES+1], char *keyin)
2020f8c8396SNick Sayer {
2030f8c8396SNick Sayer         char *p;
2040f8c8396SNick Sayer         char *s;
2050f8c8396SNick Sayer 
2060f8c8396SNick Sayer         for (p = keyin; *p; p++)
2070f8c8396SNick Sayer                 ;
2080f8c8396SNick Sayer         for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
2090f8c8396SNick Sayer                 *s = *p;
2100f8c8396SNick Sayer         }
2110f8c8396SNick Sayer         while (s >= keyout) {
2120f8c8396SNick Sayer                 *s-- = '0';
2130f8c8396SNick Sayer         }
2140f8c8396SNick Sayer }
2150f8c8396SNick Sayer 
2160f8c8396SNick Sayer static char hextab[17] = "0123456789ABCDEF";
2170f8c8396SNick Sayer 
2180f8c8396SNick Sayer /* given a DES key, cbc encrypt and translate input to terminated hex */
21921f083c0SMark Murray void
22021f083c0SMark Murray pk_encode(char *in, char *out, DesData *key)
2210f8c8396SNick Sayer {
2220f8c8396SNick Sayer 	char buf[256];
2230f8c8396SNick Sayer 	DesData i;
2240f8c8396SNick Sayer 	des_key_schedule k;
2250f8c8396SNick Sayer 	int l,op,deslen;
2260f8c8396SNick Sayer 
2270f8c8396SNick Sayer 	memset(&i,0,sizeof(i));
2280f8c8396SNick Sayer 	memset(buf,0,sizeof(buf));
2290f8c8396SNick Sayer 	deslen = ((strlen(in) + 7)/8)*8;
2300f8c8396SNick Sayer 	des_key_sched(key, k);
231d48d5be0SPeter Wemm 	des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT);
2320f8c8396SNick Sayer 	for (l=0,op=0;l<deslen;l++) {
2330f8c8396SNick Sayer 		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
2340f8c8396SNick Sayer 		out[op++] = hextab[(buf[l] & 0x0f)];
2350f8c8396SNick Sayer 	}
2360f8c8396SNick Sayer 	out[op] = '\0';
2370f8c8396SNick Sayer }
2380f8c8396SNick Sayer 
2390f8c8396SNick Sayer /* given a DES key, translate input from hex and decrypt */
24021f083c0SMark Murray void
24121f083c0SMark Murray pk_decode(char *in, char *out, DesData *key)
2420f8c8396SNick Sayer {
2430f8c8396SNick Sayer 	char buf[256];
2440f8c8396SNick Sayer 	DesData i;
2450f8c8396SNick Sayer 	des_key_schedule k;
2468fa113e5SMark Murray 	int n1,n2,op;
2478fa113e5SMark Murray 	size_t l;
2480f8c8396SNick Sayer 
2490f8c8396SNick Sayer 	memset(&i,0,sizeof(i));
2500f8c8396SNick Sayer 	memset(buf,0,sizeof(buf));
2510f8c8396SNick Sayer 	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
2520f8c8396SNick Sayer 		if(in[op] == '0' && in[op+1] == '0') {
2530f8c8396SNick Sayer 			buf[l] = '\0';
2540f8c8396SNick Sayer 			break;
2550f8c8396SNick Sayer 		}
2560f8c8396SNick Sayer 		if (in[op] > '9')
2570f8c8396SNick Sayer 			n1 = in[op] - 'A' + 10;
2580f8c8396SNick Sayer 		else
2590f8c8396SNick Sayer 			n1 = in[op] - '0';
2600f8c8396SNick Sayer 		if (in[op+1] > '9')
2610f8c8396SNick Sayer 			n2 = in[op+1] - 'A' + 10;
2620f8c8396SNick Sayer 		else
2630f8c8396SNick Sayer 			n2 = in[op+1] - '0';
2640f8c8396SNick Sayer 		buf[l] = n1*16 +n2;
2650f8c8396SNick Sayer 	}
2660f8c8396SNick Sayer 	des_key_sched(key, k);
267d48d5be0SPeter Wemm 	des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
2680f8c8396SNick Sayer 	out[strlen(in)/2] = '\0';
2690f8c8396SNick Sayer }
270