1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
32*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California.
33*7c478bd9Sstevel@tonic-gate */
34*7c478bd9Sstevel@tonic-gate
35*7c478bd9Sstevel@tonic-gate /*
36*7c478bd9Sstevel@tonic-gate * generic_key.c
37*7c478bd9Sstevel@tonic-gate */
38*7c478bd9Sstevel@tonic-gate
39*7c478bd9Sstevel@tonic-gate #include <mp.h>
40*7c478bd9Sstevel@tonic-gate #include <time.h>
41*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
42*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate #define BASEBITS (8 * sizeof (char))
45*7c478bd9Sstevel@tonic-gate #define BASE (1 << BASEBITS)
46*7c478bd9Sstevel@tonic-gate
47*7c478bd9Sstevel@tonic-gate extern void des_setparity(char *);
48*7c478bd9Sstevel@tonic-gate extern void des_setparity_g(des_block *);
49*7c478bd9Sstevel@tonic-gate
50*7c478bd9Sstevel@tonic-gate /*
51*7c478bd9Sstevel@tonic-gate * seed the random generator. Here we use the time of day and a supplied
52*7c478bd9Sstevel@tonic-gate * password for generating the seed.
53*7c478bd9Sstevel@tonic-gate */
54*7c478bd9Sstevel@tonic-gate static void
setseed(unsigned char * pass)55*7c478bd9Sstevel@tonic-gate setseed(unsigned char *pass)
56*7c478bd9Sstevel@tonic-gate {
57*7c478bd9Sstevel@tonic-gate int i;
58*7c478bd9Sstevel@tonic-gate int rseed;
59*7c478bd9Sstevel@tonic-gate struct timeval tv;
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)NULL);
62*7c478bd9Sstevel@tonic-gate rseed = tv.tv_sec + tv.tv_usec;
63*7c478bd9Sstevel@tonic-gate
64*7c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) {
65*7c478bd9Sstevel@tonic-gate rseed ^= (rseed << 8) | pass[i];
66*7c478bd9Sstevel@tonic-gate }
67*7c478bd9Sstevel@tonic-gate (void) srandom(rseed);
68*7c478bd9Sstevel@tonic-gate }
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate * Adjust the input key so that it is 0-filled on the left and store
72*7c478bd9Sstevel@tonic-gate * the results in key out.
73*7c478bd9Sstevel@tonic-gate */
74*7c478bd9Sstevel@tonic-gate static void
adjust(char * keyout,char * keyin,int keylen)75*7c478bd9Sstevel@tonic-gate adjust(char *keyout, char *keyin, int keylen)
76*7c478bd9Sstevel@tonic-gate {
77*7c478bd9Sstevel@tonic-gate char *p;
78*7c478bd9Sstevel@tonic-gate char *s;
79*7c478bd9Sstevel@tonic-gate int hexkeybytes = (keylen+3)/4;
80*7c478bd9Sstevel@tonic-gate
81*7c478bd9Sstevel@tonic-gate for (p = keyin; *p; p++);
82*7c478bd9Sstevel@tonic-gate for (s = keyout + hexkeybytes; p >= keyin; p--, s--) {
83*7c478bd9Sstevel@tonic-gate *s = *p;
84*7c478bd9Sstevel@tonic-gate }
85*7c478bd9Sstevel@tonic-gate while (s >= keyout) {
86*7c478bd9Sstevel@tonic-gate *s-- = '0';
87*7c478bd9Sstevel@tonic-gate }
88*7c478bd9Sstevel@tonic-gate }
89*7c478bd9Sstevel@tonic-gate
90*7c478bd9Sstevel@tonic-gate /*
91*7c478bd9Sstevel@tonic-gate * __generic_gen_dhkeys: Classic Diffie-Hellman key pair generation.
92*7c478bd9Sstevel@tonic-gate * Generate a Diffie-Hellman key pair of a given key length using
93*7c478bd9Sstevel@tonic-gate * the supplied modulus and root. To calculate the pair we generate
94*7c478bd9Sstevel@tonic-gate * a random key of the appropriate key length modulo the modulus.
95*7c478bd9Sstevel@tonic-gate * This random key is the private key of the key pair. We now compute
96*7c478bd9Sstevel@tonic-gate * the public key as PublicKey = root^PrivateKey % modulus. This routine
97*7c478bd9Sstevel@tonic-gate * make use of libmp to do the multiprecision interger arithmetic.
98*7c478bd9Sstevel@tonic-gate */
99*7c478bd9Sstevel@tonic-gate void
__generic_gen_dhkeys(int keylen,char * xmodulus,int proot,char * public,char * secret,char * pass)100*7c478bd9Sstevel@tonic-gate __generic_gen_dhkeys(int keylen, /* Size of keys in bits */
101*7c478bd9Sstevel@tonic-gate char *xmodulus, /* The modulus */
102*7c478bd9Sstevel@tonic-gate int proot, /* The prime root */
103*7c478bd9Sstevel@tonic-gate char *public, /* Public key */
104*7c478bd9Sstevel@tonic-gate char *secret, /* Private key */
105*7c478bd9Sstevel@tonic-gate char *pass /* password to seed with for private key */)
106*7c478bd9Sstevel@tonic-gate {
107*7c478bd9Sstevel@tonic-gate int i, len;
108*7c478bd9Sstevel@tonic-gate MINT *pk = mp_itom(0); /* Initial public key */
109*7c478bd9Sstevel@tonic-gate MINT *sk = mp_itom(0); /* Initial private key */
110*7c478bd9Sstevel@tonic-gate MINT *tmp;
111*7c478bd9Sstevel@tonic-gate MINT *base = mp_itom(BASE); /* We shift by BASEBITS */
112*7c478bd9Sstevel@tonic-gate MINT *root = mp_itom(proot); /* We get the root as a MINT */
113*7c478bd9Sstevel@tonic-gate /* Convert the modulus from a hex string to a MINT */
114*7c478bd9Sstevel@tonic-gate MINT *modulus = mp_xtom(xmodulus);
115*7c478bd9Sstevel@tonic-gate unsigned char seed;
116*7c478bd9Sstevel@tonic-gate char *xkey;
117*7c478bd9Sstevel@tonic-gate
118*7c478bd9Sstevel@tonic-gate /* Seed the random generate */
119*7c478bd9Sstevel@tonic-gate setseed((u_char *)pass);
120*7c478bd9Sstevel@tonic-gate
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate * We will break up the private key into groups of BASEBITS where
123*7c478bd9Sstevel@tonic-gate * BASEBITS is equal to the number of bits in an integer type.
124*7c478bd9Sstevel@tonic-gate * Curently, basebits is 8 so the integral type is a character.
125*7c478bd9Sstevel@tonic-gate * We will calculate the number of BASEBITS units that we need so
126*7c478bd9Sstevel@tonic-gate * that we have at least keylen bits.
127*7c478bd9Sstevel@tonic-gate */
128*7c478bd9Sstevel@tonic-gate len = ((keylen + BASEBITS - 1) / BASEBITS);
129*7c478bd9Sstevel@tonic-gate
130*7c478bd9Sstevel@tonic-gate /*
131*7c478bd9Sstevel@tonic-gate * Now for each BASEBITS we calculate a new random number.
132*7c478bd9Sstevel@tonic-gate * Shift the private key by base bits and then add the
133*7c478bd9Sstevel@tonic-gate * generated random number.
134*7c478bd9Sstevel@tonic-gate */
135*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) {
136*7c478bd9Sstevel@tonic-gate /* get a random number */
137*7c478bd9Sstevel@tonic-gate seed = random() ^ pass[i % 8];
138*7c478bd9Sstevel@tonic-gate /* Convert it to a MINT */
139*7c478bd9Sstevel@tonic-gate tmp = mp_itom(seed);
140*7c478bd9Sstevel@tonic-gate /* Shift the private key */
141*7c478bd9Sstevel@tonic-gate mp_mult(sk, base, sk);
142*7c478bd9Sstevel@tonic-gate /* Add in the new low order bits */
143*7c478bd9Sstevel@tonic-gate mp_madd(sk, tmp, sk);
144*7c478bd9Sstevel@tonic-gate /* Free tmp */
145*7c478bd9Sstevel@tonic-gate mp_mfree(tmp);
146*7c478bd9Sstevel@tonic-gate }
147*7c478bd9Sstevel@tonic-gate
148*7c478bd9Sstevel@tonic-gate /* Set timp to 0 */
149*7c478bd9Sstevel@tonic-gate tmp = mp_itom(0);
150*7c478bd9Sstevel@tonic-gate /* We get the private keys as private key modulo the modulus */
151*7c478bd9Sstevel@tonic-gate mp_mdiv(sk, modulus, tmp, sk);
152*7c478bd9Sstevel@tonic-gate /* Done with tmp */
153*7c478bd9Sstevel@tonic-gate mp_mfree(tmp);
154*7c478bd9Sstevel@tonic-gate /* The public key is root^sk % modulus */
155*7c478bd9Sstevel@tonic-gate mp_pow(root, sk, modulus, pk);
156*7c478bd9Sstevel@tonic-gate /* Convert the private key to a hex string */
157*7c478bd9Sstevel@tonic-gate xkey = mp_mtox(sk);
158*7c478bd9Sstevel@tonic-gate /* Set leading zeros if necessary and store in secret */
159*7c478bd9Sstevel@tonic-gate (void) adjust(secret, xkey, keylen);
160*7c478bd9Sstevel@tonic-gate /* Done with xkey */
161*7c478bd9Sstevel@tonic-gate free(xkey);
162*7c478bd9Sstevel@tonic-gate /* Now set xkey to the hex representation of the public key */
163*7c478bd9Sstevel@tonic-gate xkey = mp_mtox(pk);
164*7c478bd9Sstevel@tonic-gate /* Set leading zeros and store in public */
165*7c478bd9Sstevel@tonic-gate (void) adjust(public, xkey, keylen);
166*7c478bd9Sstevel@tonic-gate
167*7c478bd9Sstevel@tonic-gate /* Free storage */
168*7c478bd9Sstevel@tonic-gate free(xkey);
169*7c478bd9Sstevel@tonic-gate
170*7c478bd9Sstevel@tonic-gate mp_mfree(sk);
171*7c478bd9Sstevel@tonic-gate mp_mfree(base);
172*7c478bd9Sstevel@tonic-gate mp_mfree(pk);
173*7c478bd9Sstevel@tonic-gate mp_mfree(root);
174*7c478bd9Sstevel@tonic-gate mp_mfree(modulus);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate
177*7c478bd9Sstevel@tonic-gate /*
178*7c478bd9Sstevel@tonic-gate * Given a key extract keynum des keys
179*7c478bd9Sstevel@tonic-gate */
180*7c478bd9Sstevel@tonic-gate static void
extractdeskeys(MINT * ck,int keylen,des_block keys[],int keynum)181*7c478bd9Sstevel@tonic-gate extractdeskeys(MINT *ck, int keylen, des_block keys[], int keynum)
182*7c478bd9Sstevel@tonic-gate {
183*7c478bd9Sstevel@tonic-gate MINT *a;
184*7c478bd9Sstevel@tonic-gate short r;
185*7c478bd9Sstevel@tonic-gate int i;
186*7c478bd9Sstevel@tonic-gate short base = (1 << 8);
187*7c478bd9Sstevel@tonic-gate char *k;
188*7c478bd9Sstevel@tonic-gate /* len is the total number of bits we need for keynum des keys */
189*7c478bd9Sstevel@tonic-gate int len = 8 * sizeof (des_block) * keynum;
190*7c478bd9Sstevel@tonic-gate extern void _mp_move(MINT *, MINT *);
191*7c478bd9Sstevel@tonic-gate
192*7c478bd9Sstevel@tonic-gate /* Create a MINT a to hold the common key */
193*7c478bd9Sstevel@tonic-gate a = mp_itom(0);
194*7c478bd9Sstevel@tonic-gate _mp_move(ck, a);
195*7c478bd9Sstevel@tonic-gate
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate * Calculate the middle byte in the key. We will simply extract
199*7c478bd9Sstevel@tonic-gate * the middle bits of the key for the bits in our DES keys.
200*7c478bd9Sstevel@tonic-gate */
201*7c478bd9Sstevel@tonic-gate for (i = 0; i < ((keylen - len)/2)/8; i++)
202*7c478bd9Sstevel@tonic-gate mp_sdiv(a, base, a, &r); /* Shift the key by one byte */
203*7c478bd9Sstevel@tonic-gate
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate * Now take our middle bits referenced by a and shove them
206*7c478bd9Sstevel@tonic-gate * into the array of DES keys.
207*7c478bd9Sstevel@tonic-gate */
208*7c478bd9Sstevel@tonic-gate k = (char *)keys;
209*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (des_block) * keynum; i++) {
210*7c478bd9Sstevel@tonic-gate mp_sdiv(a, base, a, &r);
211*7c478bd9Sstevel@tonic-gate *k++ = r;
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate /* We're done with a */
215*7c478bd9Sstevel@tonic-gate mp_mfree(a);
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate /* Set the DES parity for each key */
218*7c478bd9Sstevel@tonic-gate for (i = 0; i < keynum; i++)
219*7c478bd9Sstevel@tonic-gate if (keylen == 192) /* Old broken way for compatibility */
220*7c478bd9Sstevel@tonic-gate des_setparity((char *)&keys[i]);
221*7c478bd9Sstevel@tonic-gate else
222*7c478bd9Sstevel@tonic-gate des_setparity_g(&keys[i]);
223*7c478bd9Sstevel@tonic-gate }
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate /*
227*7c478bd9Sstevel@tonic-gate * __generic_common_dhkeys: Generate a set of DES keys based on
228*7c478bd9Sstevel@tonic-gate * the Diffie-Hellman common key derived from the supplied key pair
229*7c478bd9Sstevel@tonic-gate * of the given key length using the passed in modulus. The common key
230*7c478bd9Sstevel@tonic-gate * is calculated as:
231*7c478bd9Sstevel@tonic-gate *
232*7c478bd9Sstevel@tonic-gate * ck = pk ^ sk % modulus
233*7c478bd9Sstevel@tonic-gate *
234*7c478bd9Sstevel@tonic-gate * We will use the above routine to extract a set of DES keys for the
235*7c478bd9Sstevel@tonic-gate * caller.
236*7c478bd9Sstevel@tonic-gate */
237*7c478bd9Sstevel@tonic-gate void
__generic_common_dhkeys(char * pkey,char * skey,int keylen,char * xmodulus,des_block keys[],int keynum)238*7c478bd9Sstevel@tonic-gate __generic_common_dhkeys(char *pkey, /* Public key of remote */
239*7c478bd9Sstevel@tonic-gate char *skey, /* Our private key */
240*7c478bd9Sstevel@tonic-gate int keylen, /* All the keys have this many bits */
241*7c478bd9Sstevel@tonic-gate char *xmodulus, /* The modulus */
242*7c478bd9Sstevel@tonic-gate des_block keys[], /* DES keys to fill */
243*7c478bd9Sstevel@tonic-gate int keynum /* The number of DES keys to create */)
244*7c478bd9Sstevel@tonic-gate {
245*7c478bd9Sstevel@tonic-gate /* Convert hex string representations to MINTS */
246*7c478bd9Sstevel@tonic-gate MINT *pk = mp_xtom(pkey);
247*7c478bd9Sstevel@tonic-gate MINT *sk = mp_xtom(skey);
248*7c478bd9Sstevel@tonic-gate MINT *modulus = mp_xtom(xmodulus);
249*7c478bd9Sstevel@tonic-gate /* Create a MINT for the common key */
250*7c478bd9Sstevel@tonic-gate MINT *ck = mp_itom(0);
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate /* ck = pk ^ sk % modulus */
253*7c478bd9Sstevel@tonic-gate mp_pow(pk, sk, modulus, ck);
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate /* Set the DES keys */
256*7c478bd9Sstevel@tonic-gate extractdeskeys(ck, keylen, keys, keynum);
257*7c478bd9Sstevel@tonic-gate
258*7c478bd9Sstevel@tonic-gate /* Clean up */
259*7c478bd9Sstevel@tonic-gate mp_mfree(pk);
260*7c478bd9Sstevel@tonic-gate mp_mfree(sk);
261*7c478bd9Sstevel@tonic-gate mp_mfree(modulus);
262*7c478bd9Sstevel@tonic-gate mp_mfree(ck);
263*7c478bd9Sstevel@tonic-gate }
264