xref: /freebsd/contrib/telnet/libtelnet/pk.c (revision 40a8ac8f62b535d30349faf28cf47106b7041b83)
1 /*-
2  * Copyright (c) 1991, 1993
3  *      Dave Safford.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 
33 __FBSDID("$FreeBSD$");
34 
35 /* public key routines */
36 /* functions:
37 	genkeys(char *public, char *secret)
38 	common_key(char *secret, char *public, desData *deskey)
39         pk_encode(char *in, *out, DesData *deskey);
40         pk_decode(char *in, *out, DesData *deskey);
41       where
42 	char public[HEXKEYBYTES + 1];
43 	char secret[HEXKEYBYTES + 1];
44  */
45 
46 #include <sys/time.h>
47 #include <openssl/des.h>
48 #include <fcntl.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 
53 #include "mp.h"
54 #include "pk.h"
55 
56 static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
57 
58 /*
59  * Choose top 128 bits of the common key to use as our idea key.
60  */
61 static void
62 extractideakey(MINT *ck, IdeaData *ideakey)
63 {
64         MINT *a;
65         MINT *z;
66         short r;
67         int i;
68         short base = (1 << 8);
69         char *k;
70 
71         z = mp_itom(0);
72         a = mp_itom(0);
73         mp_madd(ck, z, a);
74         for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
75                 mp_sdiv(a, base, a, &r);
76         }
77         k = (char *)ideakey;
78         for (i = 0; i < 16; i++) {
79                 mp_sdiv(a, base, a, &r);
80                 *k++ = r;
81         }
82 	mp_mfree(z);
83         mp_mfree(a);
84 }
85 
86 /*
87  * Choose middle 64 bits of the common key to use as our des key, possibly
88  * overwriting the lower order bits by setting parity.
89  */
90 static void
91 extractdeskey(MINT *ck, DesData *deskey)
92 {
93         MINT *a;
94         MINT *z;
95         short r;
96         int i;
97         short base = (1 << 8);
98         char *k;
99 
100         z = mp_itom(0);
101         a = mp_itom(0);
102         mp_madd(ck, z, a);
103         for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
104                 mp_sdiv(a, base, a, &r);
105         }
106         k = (char *)deskey;
107         for (i = 0; i < 8; i++) {
108                 mp_sdiv(a, base, a, &r);
109                 *k++ = r;
110         }
111 	mp_mfree(z);
112         mp_mfree(a);
113 }
114 
115 /*
116  * get common key from my secret key and his public key
117  */
118 void
119 common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
120 {
121         MINT *public;
122         MINT *secret;
123         MINT *common;
124 	MINT *modulus = mp_xtom(HEXMODULUS);
125 
126         public = mp_xtom(xpublic);
127         secret = mp_xtom(xsecret);
128         common = mp_itom(0);
129         mp_pow(public, secret, modulus, common);
130         extractdeskey(common, deskey);
131         extractideakey(common, ideakey);
132 	des_set_odd_parity(deskey);
133         mp_mfree(common);
134         mp_mfree(secret);
135         mp_mfree(public);
136 	mp_mfree(modulus);
137 }
138 
139 /*
140  * Generate a seed
141  */
142 static void
143 getseed(char *seed, int seedsize)
144 {
145 	int i;
146 
147 	srandomdev();
148 	for (i = 0; i < seedsize; i++) {
149 		seed[i] = random() & 0xff;
150 	}
151 }
152 
153 /*
154  * Generate a random public/secret key pair
155  */
156 void
157 genkeys(char *public, char *secret)
158 {
159         size_t i;
160 
161 #       define BASEBITS (8*sizeof(short) - 1)
162 #       define BASE (1 << BASEBITS)
163 
164         MINT *pk = mp_itom(0);
165         MINT *sk = mp_itom(0);
166         MINT *tmp;
167         MINT *base = mp_itom(BASE);
168         MINT *root = mp_itom(PROOT);
169         MINT *modulus = mp_xtom(HEXMODULUS);
170         short r;
171         unsigned short seed[KEYSIZE/BASEBITS + 1];
172         char *xkey;
173 
174         getseed((char *)seed, sizeof(seed));
175         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
176                 r = seed[i] % BASE;
177                 tmp = mp_itom(r);
178                 mp_mult(sk, base, sk);
179                 mp_madd(sk, tmp, sk);
180                 mp_mfree(tmp);
181         }
182         tmp = mp_itom(0);
183         mp_mdiv(sk, modulus, tmp, sk);
184         mp_mfree(tmp);
185         mp_pow(root, sk, modulus, pk);
186         xkey = mp_mtox(sk);
187         adjust(secret, xkey);
188         xkey = mp_mtox(pk);
189         adjust(public, xkey);
190         mp_mfree(sk);
191         mp_mfree(base);
192         mp_mfree(pk);
193         mp_mfree(root);
194         mp_mfree(modulus);
195 }
196 
197 /*
198  * Adjust the input key so that it is 0-filled on the left
199  */
200 static void
201 adjust(char keyout[HEXKEYBYTES+1], char *keyin)
202 {
203         char *p;
204         char *s;
205 
206         for (p = keyin; *p; p++)
207                 ;
208         for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
209                 *s = *p;
210         }
211         while (s >= keyout) {
212                 *s-- = '0';
213         }
214 }
215 
216 static char hextab[17] = "0123456789ABCDEF";
217 
218 /* given a DES key, cbc encrypt and translate input to terminated hex */
219 void
220 pk_encode(char *in, char *out, DesData *key)
221 {
222 	char buf[256];
223 	DesData i;
224 	des_key_schedule k;
225 	int l,op,deslen;
226 
227 	memset(&i,0,sizeof(i));
228 	memset(buf,0,sizeof(buf));
229 	deslen = ((strlen(in) + 7)/8)*8;
230 	des_key_sched(key, k);
231 	des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT);
232 	for (l=0,op=0;l<deslen;l++) {
233 		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
234 		out[op++] = hextab[(buf[l] & 0x0f)];
235 	}
236 	out[op] = '\0';
237 }
238 
239 /* given a DES key, translate input from hex and decrypt */
240 void
241 pk_decode(char *in, char *out, DesData *key)
242 {
243 	char buf[256];
244 	DesData i;
245 	des_key_schedule k;
246 	int n1,n2,op;
247 	size_t l;
248 
249 	memset(&i,0,sizeof(i));
250 	memset(buf,0,sizeof(buf));
251 	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
252 		if (in[op] > '9')
253 			n1 = in[op] - 'A' + 10;
254 		else
255 			n1 = in[op] - '0';
256 		if (in[op+1] > '9')
257 			n2 = in[op+1] - 'A' + 10;
258 		else
259 			n2 = in[op+1] - '0';
260 		buf[l] = n1*16 +n2;
261 	}
262 	des_key_sched(key, k);
263 	des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
264 	out[strlen(in)/2] = '\0';
265 }
266