xref: /freebsd/contrib/telnet/libtelnet/pk.c (revision 21f083c0a6fd6751b7da98cf93e1adad535309be)
10f8c8396SNick Sayer /* public key routines */
2bf4f84d4SMark Murray /* $FreeBSD$ */
30f8c8396SNick Sayer /* functions:
40f8c8396SNick Sayer 	genkeys(char *public, char *secret)
50f8c8396SNick Sayer 	common_key(char *secret, char *public, desData *deskey)
60f8c8396SNick Sayer         pk_encode(char *in, *out, DesData *deskey);
70f8c8396SNick Sayer         pk_decode(char *in, *out, DesData *deskey);
80f8c8396SNick Sayer       where
90f8c8396SNick Sayer 	char public[HEXKEYBYTES + 1];
100f8c8396SNick Sayer 	char secret[HEXKEYBYTES + 1];
110f8c8396SNick Sayer  */
120f8c8396SNick Sayer 
130f8c8396SNick Sayer #include <sys/time.h>
14bf4f84d4SMark Murray #include <openssl/des.h>
1521f083c0SMark Murray #include <fcntl.h>
1621f083c0SMark Murray #include <stdio.h>
1721f083c0SMark Murray #include <string.h>
180f8c8396SNick Sayer #include "mp.h"
190f8c8396SNick Sayer #include "pk.h"
2021f083c0SMark Murray #if defined(SOLARIS2) || defined(LINUX) || defined(__FreeBSD__)
210f8c8396SNick Sayer #include <stdlib.h>
220f8c8396SNick Sayer #endif
230f8c8396SNick Sayer 
2421f083c0SMark Murray static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
2521f083c0SMark Murray 
260f8c8396SNick Sayer /*
270f8c8396SNick Sayer  * Choose top 128 bits of the common key to use as our idea key.
280f8c8396SNick Sayer  */
2921f083c0SMark Murray static void
3021f083c0SMark Murray extractideakey(MINT *ck, IdeaData *ideakey)
310f8c8396SNick Sayer {
320f8c8396SNick Sayer         MINT *a;
330f8c8396SNick Sayer         MINT *z;
340f8c8396SNick Sayer         short r;
350f8c8396SNick Sayer         int i;
360f8c8396SNick Sayer         short base = (1 << 8);
370f8c8396SNick Sayer         char *k;
380f8c8396SNick Sayer 
390f8c8396SNick Sayer         z = itom(0);
400f8c8396SNick Sayer         a = itom(0);
410f8c8396SNick Sayer         madd(ck, z, a);
420f8c8396SNick Sayer         for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
430f8c8396SNick Sayer                 sdiv(a, base, a, &r);
440f8c8396SNick Sayer         }
450f8c8396SNick Sayer         k = (char *)ideakey;
460f8c8396SNick Sayer         for (i = 0; i < 16; i++) {
470f8c8396SNick Sayer                 sdiv(a, base, a, &r);
480f8c8396SNick Sayer                 *k++ = r;
490f8c8396SNick Sayer         }
500f8c8396SNick Sayer 	mfree(z);
510f8c8396SNick Sayer         mfree(a);
520f8c8396SNick Sayer }
530f8c8396SNick Sayer 
540f8c8396SNick Sayer /*
550f8c8396SNick Sayer  * Choose middle 64 bits of the common key to use as our des key, possibly
560f8c8396SNick Sayer  * overwriting the lower order bits by setting parity.
570f8c8396SNick Sayer  */
5821f083c0SMark Murray static void
5921f083c0SMark Murray extractdeskey(MINT *ck, DesData *deskey)
600f8c8396SNick Sayer {
610f8c8396SNick Sayer         MINT *a;
620f8c8396SNick Sayer         MINT *z;
630f8c8396SNick Sayer         short r;
640f8c8396SNick Sayer         int i;
650f8c8396SNick Sayer         short base = (1 << 8);
660f8c8396SNick Sayer         char *k;
670f8c8396SNick Sayer 
680f8c8396SNick Sayer         z = itom(0);
690f8c8396SNick Sayer         a = itom(0);
700f8c8396SNick Sayer         madd(ck, z, a);
710f8c8396SNick Sayer         for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
720f8c8396SNick Sayer                 sdiv(a, base, a, &r);
730f8c8396SNick Sayer         }
740f8c8396SNick Sayer         k = (char *)deskey;
750f8c8396SNick Sayer         for (i = 0; i < 8; i++) {
760f8c8396SNick Sayer                 sdiv(a, base, a, &r);
770f8c8396SNick Sayer                 *k++ = r;
780f8c8396SNick Sayer         }
790f8c8396SNick Sayer 	mfree(z);
800f8c8396SNick Sayer         mfree(a);
810f8c8396SNick Sayer }
820f8c8396SNick Sayer 
830f8c8396SNick Sayer /*
840f8c8396SNick Sayer  * get common key from my secret key and his public key
850f8c8396SNick Sayer  */
8621f083c0SMark Murray void
8721f083c0SMark Murray common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
880f8c8396SNick Sayer {
890f8c8396SNick Sayer         MINT *public;
900f8c8396SNick Sayer         MINT *secret;
910f8c8396SNick Sayer         MINT *common;
920f8c8396SNick Sayer 	MINT *modulus = xtom(HEXMODULUS);
930f8c8396SNick Sayer 
940f8c8396SNick Sayer         public = xtom(xpublic);
950f8c8396SNick Sayer         secret = xtom(xsecret);
960f8c8396SNick Sayer         common = itom(0);
970f8c8396SNick Sayer         pow(public, secret, modulus, common);
980f8c8396SNick Sayer         extractdeskey(common, deskey);
990f8c8396SNick Sayer         extractideakey(common, ideakey);
1000f8c8396SNick Sayer #if DES_OSTHOLM
1010f8c8396SNick Sayer 	des_fixup_key_parity(deskey);
1020f8c8396SNick Sayer #else
1030f8c8396SNick Sayer 	des_set_odd_parity(deskey);
1040f8c8396SNick Sayer #endif
1050f8c8396SNick Sayer         mfree(common);
1060f8c8396SNick Sayer         mfree(secret);
1070f8c8396SNick Sayer         mfree(public);
1080f8c8396SNick Sayer 	mfree(modulus);
1090f8c8396SNick Sayer }
1100f8c8396SNick Sayer 
1110f8c8396SNick Sayer /*
1120f8c8396SNick Sayer  * Generate a seed
1130f8c8396SNick Sayer  */
11421f083c0SMark Murray void
11521f083c0SMark Murray getseed(char *seed, int seedsize)
1160f8c8396SNick Sayer {
117d48d5be0SPeter Wemm 	int i;
118d48d5be0SPeter Wemm 
1198183ac8fSNick Sayer 	srandomdev();
1208183ac8fSNick Sayer 	for (i = 0; i < seedsize; i++) {
1218183ac8fSNick Sayer 		seed[i] = random() & 0xff;
1228183ac8fSNick Sayer 	}
1230f8c8396SNick Sayer }
1240f8c8396SNick Sayer 
1250f8c8396SNick Sayer /*
1260f8c8396SNick Sayer  * Generate a random public/secret key pair
1270f8c8396SNick Sayer  */
12821f083c0SMark Murray void
12921f083c0SMark Murray genkeys(char *public, char *secret)
1300f8c8396SNick Sayer {
1310f8c8396SNick Sayer         int i;
1320f8c8396SNick Sayer 
1330f8c8396SNick Sayer #       define BASEBITS (8*sizeof(short) - 1)
1340f8c8396SNick Sayer #       define BASE (1 << BASEBITS)
1350f8c8396SNick Sayer 
1360f8c8396SNick Sayer         MINT *pk = itom(0);
1370f8c8396SNick Sayer         MINT *sk = itom(0);
1380f8c8396SNick Sayer         MINT *tmp;
1390f8c8396SNick Sayer         MINT *base = itom(BASE);
1400f8c8396SNick Sayer         MINT *root = itom(PROOT);
1410f8c8396SNick Sayer         MINT *modulus = xtom(HEXMODULUS);
1420f8c8396SNick Sayer         short r;
1430f8c8396SNick Sayer         unsigned short seed[KEYSIZE/BASEBITS + 1];
1440f8c8396SNick Sayer         char *xkey;
1450f8c8396SNick Sayer 
1460f8c8396SNick Sayer         getseed((char *)seed, sizeof(seed));
1470f8c8396SNick Sayer         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
1480f8c8396SNick Sayer                 r = seed[i] % BASE;
1490f8c8396SNick Sayer                 tmp = itom(r);
1500f8c8396SNick Sayer                 mult(sk, base, sk);
1510f8c8396SNick Sayer                 madd(sk, tmp, sk);
1520f8c8396SNick Sayer                 mfree(tmp);
1530f8c8396SNick Sayer         }
1540f8c8396SNick Sayer         tmp = itom(0);
1550f8c8396SNick Sayer         mdiv(sk, modulus, tmp, sk);
1560f8c8396SNick Sayer         mfree(tmp);
1570f8c8396SNick Sayer         pow(root, sk, modulus, pk);
1580f8c8396SNick Sayer         xkey = mtox(sk);
1590f8c8396SNick Sayer         adjust(secret, xkey);
1600f8c8396SNick Sayer         xkey = mtox(pk);
1610f8c8396SNick Sayer         adjust(public, xkey);
1620f8c8396SNick Sayer         mfree(sk);
1630f8c8396SNick Sayer         mfree(base);
1640f8c8396SNick Sayer         mfree(pk);
1650f8c8396SNick Sayer         mfree(root);
1660f8c8396SNick Sayer         mfree(modulus);
1670f8c8396SNick Sayer }
1680f8c8396SNick Sayer 
1690f8c8396SNick Sayer /*
1700f8c8396SNick Sayer  * Adjust the input key so that it is 0-filled on the left
1710f8c8396SNick Sayer  */
17221f083c0SMark Murray static void
17321f083c0SMark Murray adjust(char keyout[HEXKEYBYTES+1], char *keyin)
1740f8c8396SNick Sayer {
1750f8c8396SNick Sayer         char *p;
1760f8c8396SNick Sayer         char *s;
1770f8c8396SNick Sayer 
1780f8c8396SNick Sayer         for (p = keyin; *p; p++)
1790f8c8396SNick Sayer                 ;
1800f8c8396SNick Sayer         for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
1810f8c8396SNick Sayer                 *s = *p;
1820f8c8396SNick Sayer         }
1830f8c8396SNick Sayer         while (s >= keyout) {
1840f8c8396SNick Sayer                 *s-- = '0';
1850f8c8396SNick Sayer         }
1860f8c8396SNick Sayer }
1870f8c8396SNick Sayer 
1880f8c8396SNick Sayer static char hextab[17] = "0123456789ABCDEF";
1890f8c8396SNick Sayer 
1900f8c8396SNick Sayer /* given a DES key, cbc encrypt and translate input to terminated hex */
19121f083c0SMark Murray void
19221f083c0SMark Murray pk_encode(char *in, char *out, DesData *key)
1930f8c8396SNick Sayer {
1940f8c8396SNick Sayer 	char buf[256];
1950f8c8396SNick Sayer 	DesData i;
1960f8c8396SNick Sayer 	des_key_schedule k;
1970f8c8396SNick Sayer 	int l,op,deslen;
1980f8c8396SNick Sayer 
1990f8c8396SNick Sayer 	memset(&i,0,sizeof(i));
2000f8c8396SNick Sayer 	memset(buf,0,sizeof(buf));
2010f8c8396SNick Sayer 	deslen = ((strlen(in) + 7)/8)*8;
2020f8c8396SNick Sayer 	des_key_sched(key, k);
203d48d5be0SPeter Wemm 	des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT);
2040f8c8396SNick Sayer 	for (l=0,op=0;l<deslen;l++) {
2050f8c8396SNick Sayer 		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
2060f8c8396SNick Sayer 		out[op++] = hextab[(buf[l] & 0x0f)];
2070f8c8396SNick Sayer 	}
2080f8c8396SNick Sayer 	out[op] = '\0';
2090f8c8396SNick Sayer }
2100f8c8396SNick Sayer 
2110f8c8396SNick Sayer /* given a DES key, translate input from hex and decrypt */
21221f083c0SMark Murray void
21321f083c0SMark Murray pk_decode(char *in, char *out, DesData *key)
2140f8c8396SNick Sayer {
2150f8c8396SNick Sayer 	char buf[256];
2160f8c8396SNick Sayer 	DesData i;
2170f8c8396SNick Sayer 	des_key_schedule k;
2180f8c8396SNick Sayer 	int l,n1,n2,op;
2190f8c8396SNick Sayer 
2200f8c8396SNick Sayer 	memset(&i,0,sizeof(i));
2210f8c8396SNick Sayer 	memset(buf,0,sizeof(buf));
2220f8c8396SNick Sayer 	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
2230f8c8396SNick Sayer 		if(in[op] == '0' && in[op+1] == '0') {
2240f8c8396SNick Sayer 			buf[l] = '\0';
2250f8c8396SNick Sayer 			break;
2260f8c8396SNick Sayer 		}
2270f8c8396SNick Sayer 		if (in[op] > '9')
2280f8c8396SNick Sayer 			n1 = in[op] - 'A' + 10;
2290f8c8396SNick Sayer 		else
2300f8c8396SNick Sayer 			n1 = in[op] - '0';
2310f8c8396SNick Sayer 		if (in[op+1] > '9')
2320f8c8396SNick Sayer 			n2 = in[op+1] - 'A' + 10;
2330f8c8396SNick Sayer 		else
2340f8c8396SNick Sayer 			n2 = in[op+1] - '0';
2350f8c8396SNick Sayer 		buf[l] = n1*16 +n2;
2360f8c8396SNick Sayer 	}
2370f8c8396SNick Sayer 	des_key_sched(key, k);
238d48d5be0SPeter Wemm 	des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
2390f8c8396SNick Sayer 	out[strlen(in)/2] = '\0';
2400f8c8396SNick Sayer }
241