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