xref: /freebsd/contrib/telnet/libtelnet/pk.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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 	arc4random_buf(seed, seedsize);
146 }
147 
148 /*
149  * Generate a random public/secret key pair
150  */
151 void
152 genkeys(char *public, char *secret)
153 {
154         size_t i;
155 
156 #       define BASEBITS (8*sizeof(short) - 1)
157 #       define BASE (1 << BASEBITS)
158 
159         MINT *pk = mp_itom(0);
160         MINT *sk = mp_itom(0);
161         MINT *tmp;
162         MINT *base = mp_itom((short)BASE);
163         MINT *root = mp_itom(PROOT);
164         MINT *modulus = mp_xtom(HEXMODULUS);
165         short r;
166         unsigned short seed[KEYSIZE/BASEBITS + 1];
167         char *xkey;
168 
169         getseed((char *)seed, sizeof(seed));
170         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
171                 r = seed[i] % BASE;
172                 tmp = mp_itom(r);
173                 mp_mult(sk, base, sk);
174                 mp_madd(sk, tmp, sk);
175                 mp_mfree(tmp);
176         }
177         tmp = mp_itom(0);
178         mp_mdiv(sk, modulus, tmp, sk);
179         mp_mfree(tmp);
180         mp_pow(root, sk, modulus, pk);
181         xkey = mp_mtox(sk);
182         adjust(secret, xkey);
183         xkey = mp_mtox(pk);
184         adjust(public, xkey);
185         mp_mfree(sk);
186         mp_mfree(base);
187         mp_mfree(pk);
188         mp_mfree(root);
189         mp_mfree(modulus);
190 }
191 
192 /*
193  * Adjust the input key so that it is 0-filled on the left
194  */
195 static void
196 adjust(char keyout[HEXKEYBYTES+1], char *keyin)
197 {
198         char *p;
199         char *s;
200 
201         for (p = keyin; *p; p++)
202                 ;
203         for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
204                 *s = *p;
205         }
206         while (s >= keyout) {
207                 *s-- = '0';
208         }
209 }
210 
211 static char hextab[17] = "0123456789ABCDEF";
212 
213 /* given a DES key, cbc encrypt and translate input to terminated hex */
214 void
215 pk_encode(char *in, char *out, DesData *key)
216 {
217 	char buf[256];
218 	DesData i;
219 	DES_key_schedule k;
220 	int l,op,deslen;
221 
222 	memset(&i,0,sizeof(i));
223 	memset(buf,0,sizeof(buf));
224 	deslen = ((strlen(in) + 7)/8)*8;
225 	DES_key_sched(key, &k);
226 	DES_cbc_encrypt(in, buf, deslen, &k, &i, DES_ENCRYPT);
227 	for (l=0,op=0;l<deslen;l++) {
228 		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
229 		out[op++] = hextab[(buf[l] & 0x0f)];
230 	}
231 	out[op] = '\0';
232 }
233 
234 /* given a DES key, translate input from hex and decrypt */
235 void
236 pk_decode(char *in, char *out, DesData *key)
237 {
238 	char buf[256];
239 	DesData i;
240 	DES_key_schedule k;
241 	int n1,n2,op;
242 	size_t l;
243 
244 	memset(&i,0,sizeof(i));
245 	memset(buf,0,sizeof(buf));
246 	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
247 		if (in[op] > '9')
248 			n1 = in[op] - 'A' + 10;
249 		else
250 			n1 = in[op] - '0';
251 		if (in[op+1] > '9')
252 			n2 = in[op+1] - 'A' + 10;
253 		else
254 			n2 = in[op+1] - '0';
255 		buf[l] = n1*16 +n2;
256 	}
257 	DES_key_sched(key, &k);
258 	DES_cbc_encrypt(buf, out, strlen(in) / 2, &k, &i, DES_DECRYPT);
259 	out[strlen(in)/2] = '\0';
260 }
261