xref: /freebsd/contrib/telnet/libtelnet/pk.c (revision a3c858005cae175e277f6f6735ca9eaea7eaf3c3)
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 
310f8c8396SNick Sayer /* public key routines */
320f8c8396SNick Sayer /* functions:
330f8c8396SNick Sayer 	genkeys(char *public, char *secret)
340f8c8396SNick Sayer 	common_key(char *secret, char *public, desData *deskey)
350f8c8396SNick Sayer         pk_encode(char *in, *out, DesData *deskey);
360f8c8396SNick Sayer         pk_decode(char *in, *out, DesData *deskey);
370f8c8396SNick Sayer       where
380f8c8396SNick Sayer 	char public[HEXKEYBYTES + 1];
390f8c8396SNick Sayer 	char secret[HEXKEYBYTES + 1];
400f8c8396SNick Sayer  */
410f8c8396SNick Sayer 
420f8c8396SNick Sayer #include <sys/time.h>
43bf4f84d4SMark Murray #include <openssl/des.h>
4421f083c0SMark Murray #include <fcntl.h>
4521f083c0SMark Murray #include <stdio.h>
468fa113e5SMark Murray #include <stdlib.h>
4721f083c0SMark Murray #include <string.h>
488fa113e5SMark Murray 
490f8c8396SNick Sayer #include "mp.h"
500f8c8396SNick Sayer #include "pk.h"
510f8c8396SNick Sayer 
5221f083c0SMark Murray static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
5321f083c0SMark Murray 
540f8c8396SNick Sayer /*
550f8c8396SNick Sayer  * Choose top 128 bits of the common key to use as our idea key.
560f8c8396SNick Sayer  */
5721f083c0SMark Murray static void
extractideakey(MINT * ck,IdeaData * ideakey)5821f083c0SMark Murray extractideakey(MINT *ck, IdeaData *ideakey)
590f8c8396SNick Sayer {
600f8c8396SNick Sayer         MINT *a;
610f8c8396SNick Sayer         MINT *z;
620f8c8396SNick Sayer         short r;
630f8c8396SNick Sayer         int i;
640f8c8396SNick Sayer         short base = (1 << 8);
650f8c8396SNick Sayer         char *k;
660f8c8396SNick Sayer 
67b3aaa0ccSEd Schouten         z = mp_itom(0);
68b3aaa0ccSEd Schouten         a = mp_itom(0);
69b3aaa0ccSEd Schouten         mp_madd(ck, z, a);
700f8c8396SNick Sayer         for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
71b3aaa0ccSEd Schouten                 mp_sdiv(a, base, a, &r);
720f8c8396SNick Sayer         }
730f8c8396SNick Sayer         k = (char *)ideakey;
740f8c8396SNick Sayer         for (i = 0; i < 16; i++) {
75b3aaa0ccSEd Schouten                 mp_sdiv(a, base, a, &r);
760f8c8396SNick Sayer                 *k++ = r;
770f8c8396SNick Sayer         }
78b3aaa0ccSEd Schouten 	mp_mfree(z);
79b3aaa0ccSEd Schouten         mp_mfree(a);
800f8c8396SNick Sayer }
810f8c8396SNick Sayer 
820f8c8396SNick Sayer /*
830f8c8396SNick Sayer  * Choose middle 64 bits of the common key to use as our des key, possibly
840f8c8396SNick Sayer  * overwriting the lower order bits by setting parity.
850f8c8396SNick Sayer  */
8621f083c0SMark Murray static void
extractdeskey(MINT * ck,DesData * deskey)8721f083c0SMark Murray extractdeskey(MINT *ck, DesData *deskey)
880f8c8396SNick Sayer {
890f8c8396SNick Sayer         MINT *a;
900f8c8396SNick Sayer         MINT *z;
910f8c8396SNick Sayer         short r;
920f8c8396SNick Sayer         int i;
930f8c8396SNick Sayer         short base = (1 << 8);
940f8c8396SNick Sayer         char *k;
950f8c8396SNick Sayer 
96b3aaa0ccSEd Schouten         z = mp_itom(0);
97b3aaa0ccSEd Schouten         a = mp_itom(0);
98b3aaa0ccSEd Schouten         mp_madd(ck, z, a);
990f8c8396SNick Sayer         for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
100b3aaa0ccSEd Schouten                 mp_sdiv(a, base, a, &r);
1010f8c8396SNick Sayer         }
1020f8c8396SNick Sayer         k = (char *)deskey;
1030f8c8396SNick Sayer         for (i = 0; i < 8; i++) {
104b3aaa0ccSEd Schouten                 mp_sdiv(a, base, a, &r);
1050f8c8396SNick Sayer                 *k++ = r;
1060f8c8396SNick Sayer         }
107b3aaa0ccSEd Schouten 	mp_mfree(z);
108b3aaa0ccSEd Schouten         mp_mfree(a);
1090f8c8396SNick Sayer }
1100f8c8396SNick Sayer 
1110f8c8396SNick Sayer /*
1120f8c8396SNick Sayer  * get common key from my secret key and his public key
1130f8c8396SNick Sayer  */
11421f083c0SMark Murray void
common_key(char * xsecret,char * xpublic,IdeaData * ideakey,DesData * deskey)11521f083c0SMark Murray common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
1160f8c8396SNick Sayer {
1170f8c8396SNick Sayer         MINT *public;
1180f8c8396SNick Sayer         MINT *secret;
1190f8c8396SNick Sayer         MINT *common;
120b3aaa0ccSEd Schouten 	MINT *modulus = mp_xtom(HEXMODULUS);
1210f8c8396SNick Sayer 
122b3aaa0ccSEd Schouten         public = mp_xtom(xpublic);
123b3aaa0ccSEd Schouten         secret = mp_xtom(xsecret);
124b3aaa0ccSEd Schouten         common = mp_itom(0);
125b3aaa0ccSEd Schouten         mp_pow(public, secret, modulus, common);
1260f8c8396SNick Sayer         extractdeskey(common, deskey);
1270f8c8396SNick Sayer         extractideakey(common, ideakey);
128b285c5dfSJung-uk Kim 	DES_set_odd_parity(deskey);
129b3aaa0ccSEd Schouten         mp_mfree(common);
130b3aaa0ccSEd Schouten         mp_mfree(secret);
131b3aaa0ccSEd Schouten         mp_mfree(public);
132b3aaa0ccSEd Schouten 	mp_mfree(modulus);
1330f8c8396SNick Sayer }
1340f8c8396SNick Sayer 
1350f8c8396SNick Sayer /*
1360f8c8396SNick Sayer  * Generate a seed
1370f8c8396SNick Sayer  */
1388fa113e5SMark Murray static void
getseed(char * seed,int seedsize)13921f083c0SMark Murray getseed(char *seed, int seedsize)
1400f8c8396SNick Sayer {
141*23c30549SConrad Meyer 	arc4random_buf(seed, seedsize);
1420f8c8396SNick Sayer }
1430f8c8396SNick Sayer 
1440f8c8396SNick Sayer /*
1450f8c8396SNick Sayer  * Generate a random public/secret key pair
1460f8c8396SNick Sayer  */
14721f083c0SMark Murray void
genkeys(char * public,char * secret)14821f083c0SMark Murray genkeys(char *public, char *secret)
1490f8c8396SNick Sayer {
1508fa113e5SMark Murray         size_t i;
1510f8c8396SNick Sayer 
1520f8c8396SNick Sayer #       define BASEBITS (8*sizeof(short) - 1)
1530f8c8396SNick Sayer #       define BASE (1 << BASEBITS)
1540f8c8396SNick Sayer 
155b3aaa0ccSEd Schouten         MINT *pk = mp_itom(0);
156b3aaa0ccSEd Schouten         MINT *sk = mp_itom(0);
1570f8c8396SNick Sayer         MINT *tmp;
158c4326258SDimitry Andric         MINT *base = mp_itom((short)BASE);
159b3aaa0ccSEd Schouten         MINT *root = mp_itom(PROOT);
160b3aaa0ccSEd Schouten         MINT *modulus = mp_xtom(HEXMODULUS);
1610f8c8396SNick Sayer         short r;
1620f8c8396SNick Sayer         unsigned short seed[KEYSIZE/BASEBITS + 1];
1630f8c8396SNick Sayer         char *xkey;
1640f8c8396SNick Sayer 
1650f8c8396SNick Sayer         getseed((char *)seed, sizeof(seed));
1660f8c8396SNick Sayer         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
1670f8c8396SNick Sayer                 r = seed[i] % BASE;
168b3aaa0ccSEd Schouten                 tmp = mp_itom(r);
169b3aaa0ccSEd Schouten                 mp_mult(sk, base, sk);
170b3aaa0ccSEd Schouten                 mp_madd(sk, tmp, sk);
171b3aaa0ccSEd Schouten                 mp_mfree(tmp);
1720f8c8396SNick Sayer         }
173b3aaa0ccSEd Schouten         tmp = mp_itom(0);
174b3aaa0ccSEd Schouten         mp_mdiv(sk, modulus, tmp, sk);
175b3aaa0ccSEd Schouten         mp_mfree(tmp);
176b3aaa0ccSEd Schouten         mp_pow(root, sk, modulus, pk);
177b3aaa0ccSEd Schouten         xkey = mp_mtox(sk);
1780f8c8396SNick Sayer         adjust(secret, xkey);
179b3aaa0ccSEd Schouten         xkey = mp_mtox(pk);
1800f8c8396SNick Sayer         adjust(public, xkey);
181b3aaa0ccSEd Schouten         mp_mfree(sk);
182b3aaa0ccSEd Schouten         mp_mfree(base);
183b3aaa0ccSEd Schouten         mp_mfree(pk);
184b3aaa0ccSEd Schouten         mp_mfree(root);
185b3aaa0ccSEd Schouten         mp_mfree(modulus);
1860f8c8396SNick Sayer }
1870f8c8396SNick Sayer 
1880f8c8396SNick Sayer /*
1890f8c8396SNick Sayer  * Adjust the input key so that it is 0-filled on the left
1900f8c8396SNick Sayer  */
19121f083c0SMark Murray static void
adjust(char keyout[HEXKEYBYTES+1],char * keyin)19221f083c0SMark Murray adjust(char keyout[HEXKEYBYTES+1], char *keyin)
1930f8c8396SNick Sayer {
1940f8c8396SNick Sayer         char *p;
1950f8c8396SNick Sayer         char *s;
1960f8c8396SNick Sayer 
1970f8c8396SNick Sayer         for (p = keyin; *p; p++)
1980f8c8396SNick Sayer                 ;
1990f8c8396SNick Sayer         for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
2000f8c8396SNick Sayer                 *s = *p;
2010f8c8396SNick Sayer         }
2020f8c8396SNick Sayer         while (s >= keyout) {
2030f8c8396SNick Sayer                 *s-- = '0';
2040f8c8396SNick Sayer         }
2050f8c8396SNick Sayer }
2060f8c8396SNick Sayer 
2070f8c8396SNick Sayer static char hextab[17] = "0123456789ABCDEF";
2080f8c8396SNick Sayer 
2090f8c8396SNick Sayer /* given a DES key, cbc encrypt and translate input to terminated hex */
21021f083c0SMark Murray void
pk_encode(char * in,char * out,DesData * key)21121f083c0SMark Murray pk_encode(char *in, char *out, DesData *key)
2120f8c8396SNick Sayer {
2130f8c8396SNick Sayer 	char buf[256];
2140f8c8396SNick Sayer 	DesData i;
215b285c5dfSJung-uk Kim 	DES_key_schedule k;
2160f8c8396SNick Sayer 	int l,op,deslen;
2170f8c8396SNick Sayer 
2180f8c8396SNick Sayer 	memset(&i,0,sizeof(i));
2190f8c8396SNick Sayer 	memset(buf,0,sizeof(buf));
2200f8c8396SNick Sayer 	deslen = ((strlen(in) + 7)/8)*8;
221b285c5dfSJung-uk Kim 	DES_key_sched(key, &k);
222b285c5dfSJung-uk Kim 	DES_cbc_encrypt(in, buf, deslen, &k, &i, DES_ENCRYPT);
2230f8c8396SNick Sayer 	for (l=0,op=0;l<deslen;l++) {
2240f8c8396SNick Sayer 		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
2250f8c8396SNick Sayer 		out[op++] = hextab[(buf[l] & 0x0f)];
2260f8c8396SNick Sayer 	}
2270f8c8396SNick Sayer 	out[op] = '\0';
2280f8c8396SNick Sayer }
2290f8c8396SNick Sayer 
2300f8c8396SNick Sayer /* given a DES key, translate input from hex and decrypt */
23121f083c0SMark Murray void
pk_decode(char * in,char * out,DesData * key)23221f083c0SMark Murray pk_decode(char *in, char *out, DesData *key)
2330f8c8396SNick Sayer {
2340f8c8396SNick Sayer 	char buf[256];
2350f8c8396SNick Sayer 	DesData i;
236b285c5dfSJung-uk Kim 	DES_key_schedule k;
2378fa113e5SMark Murray 	int n1,n2,op;
2388fa113e5SMark Murray 	size_t l;
2390f8c8396SNick Sayer 
2400f8c8396SNick Sayer 	memset(&i,0,sizeof(i));
2410f8c8396SNick Sayer 	memset(buf,0,sizeof(buf));
2420f8c8396SNick Sayer 	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
2430f8c8396SNick Sayer 		if (in[op] > '9')
2440f8c8396SNick Sayer 			n1 = in[op] - 'A' + 10;
2450f8c8396SNick Sayer 		else
2460f8c8396SNick Sayer 			n1 = in[op] - '0';
2470f8c8396SNick Sayer 		if (in[op+1] > '9')
2480f8c8396SNick Sayer 			n2 = in[op+1] - 'A' + 10;
2490f8c8396SNick Sayer 		else
2500f8c8396SNick Sayer 			n2 = in[op+1] - '0';
2510f8c8396SNick Sayer 		buf[l] = n1*16 +n2;
2520f8c8396SNick Sayer 	}
253b285c5dfSJung-uk Kim 	DES_key_sched(key, &k);
254b285c5dfSJung-uk Kim 	DES_cbc_encrypt(buf, out, strlen(in) / 2, &k, &i, DES_DECRYPT);
2550f8c8396SNick Sayer 	out[strlen(in)/2] = '\0';
2560f8c8396SNick Sayer }
257