xref: /freebsd/contrib/telnet/libtelnet/pk.c (revision 2f9966ff63d65bd474478888c9088eeae3f9c669)
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 /* public key routines */
32 /* functions:
33 	genkeys(char *public, char *secret)
34 	common_key(char *secret, char *public, desData *deskey)
35         pk_encode(char *in, *out, DesData *deskey);
36         pk_decode(char *in, *out, DesData *deskey);
37       where
38 	char public[HEXKEYBYTES + 1];
39 	char secret[HEXKEYBYTES + 1];
40  */
41 
42 #include <sys/time.h>
43 #include <openssl/des.h>
44 #include <fcntl.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 
49 #include "mp.h"
50 #include "pk.h"
51 
52 static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
53 
54 /*
55  * Choose top 128 bits of the common key to use as our idea key.
56  */
57 static void
58 extractideakey(MINT *ck, IdeaData *ideakey)
59 {
60         MINT *a;
61         MINT *z;
62         short r;
63         int i;
64         short base = (1 << 8);
65         char *k;
66 
67         z = mp_itom(0);
68         a = mp_itom(0);
69         mp_madd(ck, z, a);
70         for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
71                 mp_sdiv(a, base, a, &r);
72         }
73         k = (char *)ideakey;
74         for (i = 0; i < 16; i++) {
75                 mp_sdiv(a, base, a, &r);
76                 *k++ = r;
77         }
78 	mp_mfree(z);
79         mp_mfree(a);
80 }
81 
82 /*
83  * Choose middle 64 bits of the common key to use as our des key, possibly
84  * overwriting the lower order bits by setting parity.
85  */
86 static void
87 extractdeskey(MINT *ck, DesData *deskey)
88 {
89         MINT *a;
90         MINT *z;
91         short r;
92         int i;
93         short base = (1 << 8);
94         char *k;
95 
96         z = mp_itom(0);
97         a = mp_itom(0);
98         mp_madd(ck, z, a);
99         for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
100                 mp_sdiv(a, base, a, &r);
101         }
102         k = (char *)deskey;
103         for (i = 0; i < 8; i++) {
104                 mp_sdiv(a, base, a, &r);
105                 *k++ = r;
106         }
107 	mp_mfree(z);
108         mp_mfree(a);
109 }
110 
111 /*
112  * get common key from my secret key and his public key
113  */
114 void
115 common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
116 {
117         MINT *public;
118         MINT *secret;
119         MINT *common;
120 	MINT *modulus = mp_xtom(HEXMODULUS);
121 
122         public = mp_xtom(xpublic);
123         secret = mp_xtom(xsecret);
124         common = mp_itom(0);
125         mp_pow(public, secret, modulus, common);
126         extractdeskey(common, deskey);
127         extractideakey(common, ideakey);
128 	DES_set_odd_parity(deskey);
129         mp_mfree(common);
130         mp_mfree(secret);
131         mp_mfree(public);
132 	mp_mfree(modulus);
133 }
134 
135 /*
136  * Generate a seed
137  */
138 static void
139 getseed(char *seed, int seedsize)
140 {
141 	arc4random_buf(seed, seedsize);
142 }
143 
144 /*
145  * Generate a random public/secret key pair
146  */
147 void
148 genkeys(char *public, char *secret)
149 {
150         size_t i;
151 
152 #       define BASEBITS (8*sizeof(short) - 1)
153 #       define BASE (1 << BASEBITS)
154 
155         MINT *pk = mp_itom(0);
156         MINT *sk = mp_itom(0);
157         MINT *tmp;
158         MINT *base = mp_itom((short)BASE);
159         MINT *root = mp_itom(PROOT);
160         MINT *modulus = mp_xtom(HEXMODULUS);
161         short r;
162         unsigned short seed[KEYSIZE/BASEBITS + 1];
163         char *xkey;
164 
165         getseed((char *)seed, sizeof(seed));
166         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
167                 r = seed[i] % BASE;
168                 tmp = mp_itom(r);
169                 mp_mult(sk, base, sk);
170                 mp_madd(sk, tmp, sk);
171                 mp_mfree(tmp);
172         }
173         tmp = mp_itom(0);
174         mp_mdiv(sk, modulus, tmp, sk);
175         mp_mfree(tmp);
176         mp_pow(root, sk, modulus, pk);
177         xkey = mp_mtox(sk);
178         adjust(secret, xkey);
179         xkey = mp_mtox(pk);
180         adjust(public, xkey);
181         mp_mfree(sk);
182         mp_mfree(base);
183         mp_mfree(pk);
184         mp_mfree(root);
185         mp_mfree(modulus);
186 }
187 
188 /*
189  * Adjust the input key so that it is 0-filled on the left
190  */
191 static void
192 adjust(char keyout[HEXKEYBYTES+1], char *keyin)
193 {
194         char *p;
195         char *s;
196 
197         for (p = keyin; *p; p++)
198                 ;
199         for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
200                 *s = *p;
201         }
202         while (s >= keyout) {
203                 *s-- = '0';
204         }
205 }
206 
207 static char hextab[17] = "0123456789ABCDEF";
208 
209 /* given a DES key, cbc encrypt and translate input to terminated hex */
210 void
211 pk_encode(char *in, char *out, DesData *key)
212 {
213 	char buf[256];
214 	DesData i;
215 	DES_key_schedule k;
216 	int l,op,deslen;
217 
218 	memset(&i,0,sizeof(i));
219 	memset(buf,0,sizeof(buf));
220 	deslen = ((strlen(in) + 7)/8)*8;
221 	DES_key_sched(key, &k);
222 	DES_cbc_encrypt(in, buf, deslen, &k, &i, DES_ENCRYPT);
223 	for (l=0,op=0;l<deslen;l++) {
224 		out[op++] = hextab[(buf[l] & 0xf0) >> 4];
225 		out[op++] = hextab[(buf[l] & 0x0f)];
226 	}
227 	out[op] = '\0';
228 }
229 
230 /* given a DES key, translate input from hex and decrypt */
231 void
232 pk_decode(char *in, char *out, DesData *key)
233 {
234 	char buf[256];
235 	DesData i;
236 	DES_key_schedule k;
237 	int n1,n2,op;
238 	size_t l;
239 
240 	memset(&i,0,sizeof(i));
241 	memset(buf,0,sizeof(buf));
242 	for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
243 		if (in[op] > '9')
244 			n1 = in[op] - 'A' + 10;
245 		else
246 			n1 = in[op] - '0';
247 		if (in[op+1] > '9')
248 			n2 = in[op+1] - 'A' + 10;
249 		else
250 			n2 = in[op+1] - '0';
251 		buf[l] = n1*16 +n2;
252 	}
253 	DES_key_sched(key, &k);
254 	DES_cbc_encrypt(buf, out, strlen(in) / 2, &k, &i, DES_DECRYPT);
255 	out[strlen(in)/2] = '\0';
256 }
257