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 2003 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 #pragma ident "%Z%%M% %I% %E% SMI"
36*7c478bd9Sstevel@tonic-gate
37*7c478bd9Sstevel@tonic-gate #include "mt.h"
38*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
39*7c478bd9Sstevel@tonic-gate #include <mp.h>
40*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
41*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
42*7c478bd9Sstevel@tonic-gate #include <thread.h>
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate extern long random();
45*7c478bd9Sstevel@tonic-gate extern void _mp_move(MINT *, MINT *);
46*7c478bd9Sstevel@tonic-gate extern void des_setparity(char *);
47*7c478bd9Sstevel@tonic-gate static void adjust();
48*7c478bd9Sstevel@tonic-gate void __gen_dhkeys();
49*7c478bd9Sstevel@tonic-gate
50*7c478bd9Sstevel@tonic-gate static MINT *MODULUS_192_0;
51*7c478bd9Sstevel@tonic-gate static mutex_t mod_192_0_lck = DEFAULTMUTEX;
52*7c478bd9Sstevel@tonic-gate static bool_t first_time = TRUE;
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate * symbol names for the entry points into the Diffie-Hellman
56*7c478bd9Sstevel@tonic-gate * GSS mech backend routines
57*7c478bd9Sstevel@tonic-gate */
58*7c478bd9Sstevel@tonic-gate static char dl_gen_funcname[] = "__dl_gen_dhkeys";
59*7c478bd9Sstevel@tonic-gate static char dl_gen_common_funcname[] = "__dl_gen_common_dhkeys";
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate * Generate a seed
63*7c478bd9Sstevel@tonic-gate */
64*7c478bd9Sstevel@tonic-gate static void
getseed(seed,seedsize,pass)65*7c478bd9Sstevel@tonic-gate getseed(seed, seedsize, pass)
66*7c478bd9Sstevel@tonic-gate char *seed;
67*7c478bd9Sstevel@tonic-gate int seedsize;
68*7c478bd9Sstevel@tonic-gate unsigned char *pass;
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate int i;
71*7c478bd9Sstevel@tonic-gate int rseed;
72*7c478bd9Sstevel@tonic-gate struct timeval tv;
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)NULL);
75*7c478bd9Sstevel@tonic-gate rseed = tv.tv_sec + tv.tv_usec;
76*7c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) {
77*7c478bd9Sstevel@tonic-gate rseed ^= (rseed << 8) | pass[i];
78*7c478bd9Sstevel@tonic-gate }
79*7c478bd9Sstevel@tonic-gate (void) srandom(rseed);
80*7c478bd9Sstevel@tonic-gate
81*7c478bd9Sstevel@tonic-gate for (i = 0; i < seedsize; i++) {
82*7c478bd9Sstevel@tonic-gate seed[i] = (random() & 0xff) ^ pass[i % 8];
83*7c478bd9Sstevel@tonic-gate }
84*7c478bd9Sstevel@tonic-gate }
85*7c478bd9Sstevel@tonic-gate
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate * Adjust the input key so that it is 0-filled on the left
88*7c478bd9Sstevel@tonic-gate */
89*7c478bd9Sstevel@tonic-gate static void
adjust(keyout,keyin)90*7c478bd9Sstevel@tonic-gate adjust(keyout, keyin)
91*7c478bd9Sstevel@tonic-gate char keyout[HEXKEYBYTES + 1];
92*7c478bd9Sstevel@tonic-gate char *keyin;
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate char *p;
95*7c478bd9Sstevel@tonic-gate char *s;
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate for (p = keyin; *p; p++)
98*7c478bd9Sstevel@tonic-gate ;
99*7c478bd9Sstevel@tonic-gate for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
100*7c478bd9Sstevel@tonic-gate *s = *p;
101*7c478bd9Sstevel@tonic-gate }
102*7c478bd9Sstevel@tonic-gate while (s >= keyout) {
103*7c478bd9Sstevel@tonic-gate *s-- = '0';
104*7c478bd9Sstevel@tonic-gate }
105*7c478bd9Sstevel@tonic-gate }
106*7c478bd9Sstevel@tonic-gate
107*7c478bd9Sstevel@tonic-gate /*
108*7c478bd9Sstevel@tonic-gate * generate a Diffie-Hellman key-pair based on the given password.
109*7c478bd9Sstevel@tonic-gate * public and secret are buffers of size HEXKEYBYTES + 1.
110*7c478bd9Sstevel@tonic-gate */
111*7c478bd9Sstevel@tonic-gate void
__gen_dhkeys(public,secret,pass)112*7c478bd9Sstevel@tonic-gate __gen_dhkeys(public, secret, pass)
113*7c478bd9Sstevel@tonic-gate char *public;
114*7c478bd9Sstevel@tonic-gate char *secret;
115*7c478bd9Sstevel@tonic-gate char *pass;
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate int i;
118*7c478bd9Sstevel@tonic-gate
119*7c478bd9Sstevel@tonic-gate #define BASEBITS (8 * sizeof (short) - 1)
120*7c478bd9Sstevel@tonic-gate #define BASE (1 << BASEBITS)
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate MINT *pk = mp_itom(0);
123*7c478bd9Sstevel@tonic-gate MINT *sk = mp_itom(0);
124*7c478bd9Sstevel@tonic-gate MINT *tmp;
125*7c478bd9Sstevel@tonic-gate MINT *base = mp_itom(BASE/2); /* BASE won't fit in a short */
126*7c478bd9Sstevel@tonic-gate MINT *root = mp_itom(PROOT);
127*7c478bd9Sstevel@tonic-gate MINT *modulus = mp_xtom(HEXMODULUS);
128*7c478bd9Sstevel@tonic-gate unsigned short r;
129*7c478bd9Sstevel@tonic-gate unsigned short seed[KEYSIZE/BASEBITS + 1];
130*7c478bd9Sstevel@tonic-gate char *xkey;
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate /* multiply base by 2 to get BASE */
133*7c478bd9Sstevel@tonic-gate tmp = mp_itom(2);
134*7c478bd9Sstevel@tonic-gate mp_mult(base, tmp, base);
135*7c478bd9Sstevel@tonic-gate mp_mfree(tmp);
136*7c478bd9Sstevel@tonic-gate
137*7c478bd9Sstevel@tonic-gate getseed((char *)seed, (int)sizeof (seed), (uchar_t *)pass);
138*7c478bd9Sstevel@tonic-gate for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
139*7c478bd9Sstevel@tonic-gate r = seed[i] % ((unsigned short)BASE);
140*7c478bd9Sstevel@tonic-gate tmp = mp_itom(r);
141*7c478bd9Sstevel@tonic-gate mp_mult(sk, base, sk);
142*7c478bd9Sstevel@tonic-gate mp_madd(sk, tmp, sk);
143*7c478bd9Sstevel@tonic-gate mp_mfree(tmp);
144*7c478bd9Sstevel@tonic-gate }
145*7c478bd9Sstevel@tonic-gate tmp = mp_itom(0);
146*7c478bd9Sstevel@tonic-gate mp_mdiv(sk, modulus, tmp, sk);
147*7c478bd9Sstevel@tonic-gate mp_mfree(tmp);
148*7c478bd9Sstevel@tonic-gate mp_pow(root, sk, modulus, pk);
149*7c478bd9Sstevel@tonic-gate xkey = mp_mtox(sk);
150*7c478bd9Sstevel@tonic-gate (void) adjust(secret, xkey);
151*7c478bd9Sstevel@tonic-gate xkey = mp_mtox(pk);
152*7c478bd9Sstevel@tonic-gate (void) adjust(public, xkey);
153*7c478bd9Sstevel@tonic-gate mp_mfree(sk);
154*7c478bd9Sstevel@tonic-gate mp_mfree(base);
155*7c478bd9Sstevel@tonic-gate mp_mfree(pk);
156*7c478bd9Sstevel@tonic-gate mp_mfree(root);
157*7c478bd9Sstevel@tonic-gate mp_mfree(modulus);
158*7c478bd9Sstevel@tonic-gate }
159*7c478bd9Sstevel@tonic-gate
160*7c478bd9Sstevel@tonic-gate
161*7c478bd9Sstevel@tonic-gate /*
162*7c478bd9Sstevel@tonic-gate * Generic key size Diffie-Hellman key pair generation routine. For classic
163*7c478bd9Sstevel@tonic-gate * AUTH_DES, just call the current routine to handle it. Else, call the
164*7c478bd9Sstevel@tonic-gate * one in the appro GSS mech backend.
165*7c478bd9Sstevel@tonic-gate *
166*7c478bd9Sstevel@tonic-gate */
167*7c478bd9Sstevel@tonic-gate int
__gen_dhkeys_g(char * pkey,char * skey,keylen_t keylen,algtype_t algtype,char * pass)168*7c478bd9Sstevel@tonic-gate __gen_dhkeys_g(char *pkey, /* out */
169*7c478bd9Sstevel@tonic-gate char *skey, /* out */
170*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */
171*7c478bd9Sstevel@tonic-gate algtype_t algtype, /* in */
172*7c478bd9Sstevel@tonic-gate char *pass) /* in */
173*7c478bd9Sstevel@tonic-gate {
174*7c478bd9Sstevel@tonic-gate const int classic_des = keylen == 192 && algtype == 0;
175*7c478bd9Sstevel@tonic-gate
176*7c478bd9Sstevel@tonic-gate if (! pkey || ! skey || ! pass)
177*7c478bd9Sstevel@tonic-gate return (0);
178*7c478bd9Sstevel@tonic-gate
179*7c478bd9Sstevel@tonic-gate if (classic_des) {
180*7c478bd9Sstevel@tonic-gate __gen_dhkeys(pkey, skey, pass);
181*7c478bd9Sstevel@tonic-gate return (1);
182*7c478bd9Sstevel@tonic-gate } else {
183*7c478bd9Sstevel@tonic-gate int (*dlfp)(); /* func ptr to dynamic loaded lib */
184*7c478bd9Sstevel@tonic-gate
185*7c478bd9Sstevel@tonic-gate if (dlfp = (int (*)())__nis_get_mechanism_symbol(keylen,
186*7c478bd9Sstevel@tonic-gate algtype,
187*7c478bd9Sstevel@tonic-gate dl_gen_funcname)) {
188*7c478bd9Sstevel@tonic-gate (*dlfp)(pkey, skey, pass); /* void */
189*7c478bd9Sstevel@tonic-gate return (1);
190*7c478bd9Sstevel@tonic-gate }
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate return (0);
194*7c478bd9Sstevel@tonic-gate }
195*7c478bd9Sstevel@tonic-gate
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate * Choose middle 64 bits of the common key to use as our des key, possibly
199*7c478bd9Sstevel@tonic-gate * overwriting the lower order bits by setting parity.
200*7c478bd9Sstevel@tonic-gate *
201*7c478bd9Sstevel@tonic-gate * (copied/moved) from keyserv's setkey.c for the DH extensions.
202*7c478bd9Sstevel@tonic-gate */
203*7c478bd9Sstevel@tonic-gate int
__extractdeskey(ck,deskey)204*7c478bd9Sstevel@tonic-gate __extractdeskey(ck, deskey)
205*7c478bd9Sstevel@tonic-gate MINT *ck;
206*7c478bd9Sstevel@tonic-gate des_block *deskey;
207*7c478bd9Sstevel@tonic-gate {
208*7c478bd9Sstevel@tonic-gate MINT *a;
209*7c478bd9Sstevel@tonic-gate short r;
210*7c478bd9Sstevel@tonic-gate int i;
211*7c478bd9Sstevel@tonic-gate short base = (1 << 8);
212*7c478bd9Sstevel@tonic-gate char *k;
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate a = mp_itom(0);
215*7c478bd9Sstevel@tonic-gate _mp_move(ck, a);
216*7c478bd9Sstevel@tonic-gate for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
217*7c478bd9Sstevel@tonic-gate mp_sdiv(a, base, a, &r);
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate k = deskey->c;
220*7c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) {
221*7c478bd9Sstevel@tonic-gate mp_sdiv(a, base, a, &r);
222*7c478bd9Sstevel@tonic-gate *k++ = r;
223*7c478bd9Sstevel@tonic-gate }
224*7c478bd9Sstevel@tonic-gate mp_mfree(a);
225*7c478bd9Sstevel@tonic-gate des_setparity((char *)deskey);
226*7c478bd9Sstevel@tonic-gate return (0);
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate /*
231*7c478bd9Sstevel@tonic-gate * Set the modulus for all our 192bit (algtype=0) Diffie-Hellman operations
232*7c478bd9Sstevel@tonic-gate */
233*7c478bd9Sstevel@tonic-gate static void
setmodulus_192_0(void)234*7c478bd9Sstevel@tonic-gate setmodulus_192_0(void)
235*7c478bd9Sstevel@tonic-gate {
236*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&mod_192_0_lck);
237*7c478bd9Sstevel@tonic-gate if (first_time) {
238*7c478bd9Sstevel@tonic-gate first_time = FALSE;
239*7c478bd9Sstevel@tonic-gate MODULUS_192_0 = mp_xtom(HEXMODULUS);
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&mod_192_0_lck);
242*7c478bd9Sstevel@tonic-gate }
243*7c478bd9Sstevel@tonic-gate
244*7c478bd9Sstevel@tonic-gate /*
245*7c478bd9Sstevel@tonic-gate * Generic key size Diffie-Hellman common key generation routine.
246*7c478bd9Sstevel@tonic-gate * For classic AUTH_DES, do it inline like it's already done in several
247*7c478bd9Sstevel@tonic-gate * places (keyserv being one place). For new long key sizes,
248*7c478bd9Sstevel@tonic-gate * call the appro GSS mech backend routine.
249*7c478bd9Sstevel@tonic-gate *
250*7c478bd9Sstevel@tonic-gate * Arg 'keynum' is the size of the 'deskeys' array. It should be a 1
251*7c478bd9Sstevel@tonic-gate * classic AUTH_DES and a 3 for new long DH keys.
252*7c478bd9Sstevel@tonic-gate *
253*7c478bd9Sstevel@tonic-gate * Returns 1 on success and 0 on err.
254*7c478bd9Sstevel@tonic-gate */
255*7c478bd9Sstevel@tonic-gate int
__gen_common_dhkeys_g(char * xpublic,char * xsecret,keylen_t keylen,algtype_t algtype,des_block deskeys[],keynum_t keynum)256*7c478bd9Sstevel@tonic-gate __gen_common_dhkeys_g(char *xpublic, /* in */
257*7c478bd9Sstevel@tonic-gate char *xsecret, /* in */
258*7c478bd9Sstevel@tonic-gate keylen_t keylen, /* in */
259*7c478bd9Sstevel@tonic-gate algtype_t algtype, /* in */
260*7c478bd9Sstevel@tonic-gate des_block deskeys[], /* out */
261*7c478bd9Sstevel@tonic-gate keynum_t keynum) /* in */
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate const int classic_des = keylen == 192 && algtype == 0;
264*7c478bd9Sstevel@tonic-gate
265*7c478bd9Sstevel@tonic-gate if (! xpublic || ! xsecret || ! deskeys)
266*7c478bd9Sstevel@tonic-gate return (0);
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate if (classic_des) {
269*7c478bd9Sstevel@tonic-gate MINT *common;
270*7c478bd9Sstevel@tonic-gate MINT *public;
271*7c478bd9Sstevel@tonic-gate MINT *secret;
272*7c478bd9Sstevel@tonic-gate
273*7c478bd9Sstevel@tonic-gate setmodulus_192_0();
274*7c478bd9Sstevel@tonic-gate
275*7c478bd9Sstevel@tonic-gate public = mp_xtom(xpublic);
276*7c478bd9Sstevel@tonic-gate secret = mp_xtom(xsecret);
277*7c478bd9Sstevel@tonic-gate common = mp_itom(0);
278*7c478bd9Sstevel@tonic-gate mp_pow(public, secret, MODULUS_192_0, common);
279*7c478bd9Sstevel@tonic-gate (void) __extractdeskey(common, &deskeys[0]);
280*7c478bd9Sstevel@tonic-gate return (1);
281*7c478bd9Sstevel@tonic-gate } else {
282*7c478bd9Sstevel@tonic-gate int (*dlfp)(); /* func ptr to dynamically loaded lib */
283*7c478bd9Sstevel@tonic-gate
284*7c478bd9Sstevel@tonic-gate if (dlfp = (int (*)())__nis_get_mechanism_symbol(keylen,
285*7c478bd9Sstevel@tonic-gate algtype,
286*7c478bd9Sstevel@tonic-gate dl_gen_common_funcname)) {
287*7c478bd9Sstevel@tonic-gate /* function called will have void return value */
288*7c478bd9Sstevel@tonic-gate (*dlfp)(xpublic, xsecret, deskeys, keynum);
289*7c478bd9Sstevel@tonic-gate return (1);
290*7c478bd9Sstevel@tonic-gate }
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate
293*7c478bd9Sstevel@tonic-gate return (0);
294*7c478bd9Sstevel@tonic-gate }
295