4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
35 #pragma ident "%Z%%M% %I% %E% SMI"
39 #include <rpc/key_prot.h>
40 #include <rpcsvc/nis_dhext.h>
44 extern void _mp_move(MINT
*, MINT
*);
45 extern void des_setparity(char *);
49 static MINT
*MODULUS_192_0
;
50 static mutex_t mod_192_0_lck
= DEFAULTMUTEX
;
51 static bool_t first_time
= TRUE
;
54 * symbol names for the entry points into the Diffie-Hellman
55 * GSS mech backend routines
57 static char dl_gen_funcname
[] = "__dl_gen_dhkeys";
58 static char dl_gen_common_funcname
[] = "__dl_gen_common_dhkeys";
64 getseed(seed
, seedsize
, pass
)
73 (void) gettimeofday(&tv
, NULL
);
74 rseed
= tv
.tv_sec
+ tv
.tv_usec
;
75 for (i
= 0; i
< 8; i
++) {
76 rseed
^= (rseed
<< 8) | pass
[i
];
78 (void) srandom(rseed
);
80 for (i
= 0; i
< seedsize
; i
++) {
81 seed
[i
] = (random() & 0xff) ^ pass
[i
% 8];
86 * Adjust the input key so that it is 0-filled on the left
90 char keyout
[HEXKEYBYTES
+ 1];
96 for (p
= keyin
; *p
; p
++)
98 for (s
= keyout
+ HEXKEYBYTES
; p
>= keyin
; p
--, s
--) {
101 while (s
>= keyout
) {
107 * generate a Diffie-Hellman key-pair based on the given password.
108 * public and secret are buffers of size HEXKEYBYTES + 1.
111 __gen_dhkeys(public, secret
, pass
)
118 #define BASEBITS (8 * sizeof (short) - 1)
119 #define BASE (1 << BASEBITS)
121 MINT
*pk
= mp_itom(0);
122 MINT
*sk
= mp_itom(0);
124 MINT
*base
= mp_itom(BASE
/2); /* BASE won't fit in a short */
125 MINT
*root
= mp_itom(PROOT
);
126 MINT
*modulus
= mp_xtom(HEXMODULUS
);
128 unsigned short seed
[KEYSIZE
/BASEBITS
+ 1];
131 /* multiply base by 2 to get BASE */
133 mp_mult(base
, tmp
, base
);
136 getseed((char *)seed
, (int)sizeof (seed
), (uchar_t
*)pass
);
137 for (i
= 0; i
< KEYSIZE
/BASEBITS
+ 1; i
++) {
138 r
= seed
[i
] % ((unsigned short)BASE
);
140 mp_mult(sk
, base
, sk
);
141 mp_madd(sk
, tmp
, sk
);
145 mp_mdiv(sk
, modulus
, tmp
, sk
);
147 mp_pow(root
, sk
, modulus
, pk
);
149 (void) adjust(secret
, xkey
);
151 (void) adjust(public, xkey
);
161 * Generic key size Diffie-Hellman key pair generation routine. For classic
162 * AUTH_DES, just call the current routine to handle it. Else, call the
163 * one in the appro GSS mech backend.
167 __gen_dhkeys_g(char *pkey
, /* out */
168 char *skey
, /* out */
169 keylen_t keylen
, /* in */
170 algtype_t algtype
, /* in */
173 const int classic_des
= keylen
== 192 && algtype
== 0;
175 if (! pkey
|| ! skey
|| ! pass
)
179 __gen_dhkeys(pkey
, skey
, pass
);
182 int (*dlfp
)(); /* func ptr to dynamic loaded lib */
184 if (dlfp
= (int (*)())__nis_get_mechanism_symbol(keylen
,
187 (*dlfp
)(pkey
, skey
, pass
); /* void */
197 * Choose middle 64 bits of the common key to use as our des key, possibly
198 * overwriting the lower order bits by setting parity.
200 * (copied/moved) from keyserv's setkey.c for the DH extensions.
203 __extractdeskey(ck
, deskey
)
210 short base
= (1 << 8);
215 for (i
= 0; i
< ((KEYSIZE
- 64) / 2) / 8; i
++) {
216 mp_sdiv(a
, base
, a
, &r
);
219 for (i
= 0; i
< 8; i
++) {
220 mp_sdiv(a
, base
, a
, &r
);
224 des_setparity((char *)deskey
);
230 * Set the modulus for all our 192bit (algtype=0) Diffie-Hellman operations
233 setmodulus_192_0(void)
235 (void) mutex_lock(&mod_192_0_lck
);
238 MODULUS_192_0
= mp_xtom(HEXMODULUS
);
240 (void) mutex_unlock(&mod_192_0_lck
);
244 * Generic key size Diffie-Hellman common key generation routine.
245 * For classic AUTH_DES, do it inline like it's already done in several
246 * places (keyserv being one place). For new long key sizes,
247 * call the appro GSS mech backend routine.
249 * Arg 'keynum' is the size of the 'deskeys' array. It should be a 1
250 * classic AUTH_DES and a 3 for new long DH keys.
252 * Returns 1 on success and 0 on err.
255 __gen_common_dhkeys_g(char *xpublic
, /* in */
256 char *xsecret
, /* in */
257 keylen_t keylen
, /* in */
258 algtype_t algtype
, /* in */
259 des_block deskeys
[], /* out */
260 keynum_t keynum
) /* in */
262 const int classic_des
= keylen
== 192 && algtype
== 0;
264 if (! xpublic
|| ! xsecret
|| ! deskeys
)
274 public = mp_xtom(xpublic
);
275 secret
= mp_xtom(xsecret
);
277 mp_pow(public, secret
, MODULUS_192_0
, common
);
278 (void) __extractdeskey(common
, &deskeys
[0]);
281 int (*dlfp
)(); /* func ptr to dynamically loaded lib */
283 if (dlfp
= (int (*)())__nis_get_mechanism_symbol(keylen
,
285 dl_gen_common_funcname
)) {
286 /* function called will have void return value */
287 (*dlfp
)(xpublic
, xsecret
, deskeys
, keynum
);