]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/telnet/libtelnet/pk.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / crypto / telnet / libtelnet / pk.c
1 /* public key routines */
2 /* $FreeBSD$ */
3 /* functions:
4         genkeys(char *public, char *secret)
5         common_key(char *secret, char *public, desData *deskey)
6         pk_encode(char *in, *out, DesData *deskey);
7         pk_decode(char *in, *out, DesData *deskey);
8       where
9         char public[HEXKEYBYTES + 1];
10         char secret[HEXKEYBYTES + 1];
11  */
12
13 #include <stdio.h>
14 #include <sys/time.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <openssl/des.h>
18 #include "mp.h"
19 #include "pk.h"
20 #if defined(SOLARIS2) || defined(LINUX)
21 #include <stdlib.h>
22 #endif
23  
24 /*
25  * Choose top 128 bits of the common key to use as our idea key.
26  */
27 static
28 extractideakey(ck, ideakey)
29         MINT *ck;
30         IdeaData *ideakey;
31 {
32         MINT *a;
33         MINT *z;
34         short r;
35         int i;
36         short base = (1 << 8);
37         char *k;
38
39         z = itom(0);
40         a = itom(0);
41         madd(ck, z, a);
42         for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
43                 sdiv(a, base, a, &r);
44         }
45         k = (char *)ideakey;
46         for (i = 0; i < 16; i++) {
47                 sdiv(a, base, a, &r);
48                 *k++ = r;
49         }
50         mfree(z);
51         mfree(a);
52 }
53
54 /*
55  * Choose middle 64 bits of the common key to use as our des key, possibly
56  * overwriting the lower order bits by setting parity. 
57  */
58 static
59 extractdeskey(ck, deskey)
60         MINT *ck;
61         DesData *deskey;
62 {
63         MINT *a;
64         MINT *z;
65         short r;
66         int i;
67         short base = (1 << 8);
68         char *k;
69
70         z = itom(0);
71         a = itom(0);
72         madd(ck, z, a);
73         for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
74                 sdiv(a, base, a, &r);
75         }
76         k = (char *)deskey;
77         for (i = 0; i < 8; i++) {
78                 sdiv(a, base, a, &r);
79                 *k++ = r;
80         }
81         mfree(z);
82         mfree(a);
83 }
84
85 /*
86  * get common key from my secret key and his public key
87  */
88 void common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
89 {
90         MINT *public;
91         MINT *secret;
92         MINT *common;
93         MINT *modulus = xtom(HEXMODULUS);
94
95         public = xtom(xpublic);
96         secret = xtom(xsecret);
97         common = itom(0);
98         pow(public, secret, modulus, common);
99         extractdeskey(common, deskey);
100         extractideakey(common, ideakey);
101 #if DES_OSTHOLM
102         des_fixup_key_parity(deskey);
103 #else
104         des_set_odd_parity(deskey);
105 #endif
106         mfree(common);
107         mfree(secret);
108         mfree(public);
109         mfree(modulus);
110 }
111
112
113 /*
114  * Generate a seed
115  */
116 void getseed(seed, seedsize)
117         char *seed;
118         int seedsize;
119 {
120         int i,f;
121         int rseed;
122         struct timeval tv;
123         long devrand;
124
125         (void)gettimeofday(&tv, (struct timezone *)NULL);
126         rseed = tv.tv_sec + tv.tv_usec;
127 /* XXX What the hell is this?! */
128         for (i = 0; i < 8; i++) {
129                 rseed ^= (rseed << 8);
130         }
131
132         f=open("/dev/random",O_NONBLOCK|O_RDONLY);
133         if (f>=0)
134         {
135                 read(f,&devrand,sizeof(devrand));
136                 close(f);
137         }
138         srand48((long)rseed^devrand);
139
140         for (i = 0; i < seedsize; i++) {
141                 seed[i] = (lrand48() & 0xff);
142         }
143 }
144
145
146 /*
147  * Generate a random public/secret key pair
148  */
149 void genkeys(public, secret)
150         char *public;
151         char *secret;
152 {
153         int i;
154  
155 #       define BASEBITS (8*sizeof(short) - 1)
156 #       define BASE (1 << BASEBITS)
157  
158         MINT *pk = itom(0);
159         MINT *sk = itom(0);
160         MINT *tmp;
161         MINT *base = itom(BASE);
162         MINT *root = itom(PROOT);
163         MINT *modulus = xtom(HEXMODULUS);
164         short r;
165         unsigned short seed[KEYSIZE/BASEBITS + 1];
166         char *xkey;
167
168         getseed((char *)seed, sizeof(seed));    
169         for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
170                 r = seed[i] % BASE;
171                 tmp = itom(r);
172                 mult(sk, base, sk);
173                 madd(sk, tmp, sk);
174                 mfree(tmp);  
175         }
176         tmp = itom(0);
177         mdiv(sk, modulus, tmp, sk);
178         mfree(tmp);
179         pow(root, sk, modulus, pk); 
180         xkey = mtox(sk);   
181         adjust(secret, xkey);
182         xkey = mtox(pk);
183         adjust(public, xkey);
184         mfree(sk);
185         mfree(base);
186         mfree(pk);
187         mfree(root);
188         mfree(modulus);
189
190
191 /*
192  * Adjust the input key so that it is 0-filled on the left
193  */
194 adjust(keyout, keyin)
195         char keyout[HEXKEYBYTES+1];
196         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 pk_encode(in, out, key)
215 char *in,*out;
216 DesData *key;
217 {
218         char buf[256];
219         DesData i;
220         des_key_schedule k;
221         int l,op,deslen;
222
223         memset(&i,0,sizeof(i));
224         memset(buf,0,sizeof(buf));
225         deslen = ((strlen(in) + 7)/8)*8;
226         des_key_sched(key, k);
227         des_cbc_encrypt((des_cblock *)in,(des_cblock *)buf,deslen,
228                 k,&i,DES_ENCRYPT);
229         for (l=0,op=0;l<deslen;l++) {
230                 out[op++] = hextab[(buf[l] & 0xf0) >> 4];
231                 out[op++] = hextab[(buf[l] & 0x0f)];
232         }
233         out[op] = '\0';
234 }
235
236 /* given a DES key, translate input from hex and decrypt */
237 void pk_decode(in, out, key)
238 char *in,*out;
239 DesData *key;
240 {
241         char buf[256];
242         DesData i;
243         des_key_schedule k;
244         int l,n1,n2,op;
245
246         memset(&i,0,sizeof(i));
247         memset(buf,0,sizeof(buf));
248         for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
249                 if(in[op] == '0' && in[op+1] == '0') {
250                         buf[l] = '\0';
251                         break;
252                 }
253                 if (in[op] > '9')
254                         n1 = in[op] - 'A' + 10;
255                 else
256                         n1 = in[op] - '0';
257                 if (in[op+1] > '9')
258                         n2 = in[op+1] - 'A' + 10;
259                 else
260                         n2 = in[op+1] - '0';
261                 buf[l] = n1*16 +n2;
262         }
263         des_key_sched(key, k);
264         des_cbc_encrypt((des_cblock *)buf,(des_cblock *)out,strlen(in)/2,
265                 k,&i,DES_DECRYPT);
266         out[strlen(in)/2] = '\0';
267 }