4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
27 * This file contains DH helper routines common to
28 * the PKCS11 soft token code and the kernel DH code.
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
36 #include <sys/param.h>
39 #include <cryptoutil.h>
42 #include <sys/crypto/common.h>
43 #include <des/des_impl.h>
48 convert_rv(BIG_ERR_CODE err
)
56 return (CKR_HOST_MEMORY
);
59 return (CKR_DEVICE_ERROR
);
61 case BIG_INVALID_ARGS
:
62 return (CKR_ARGUMENTS_BAD
);
66 return (CKR_GENERAL_ERROR
);
72 DH_key_init(DHkey
*key
, int size
)
74 BIG_ERR_CODE err
= BIG_OK
;
77 len
= BITLEN2BIGNUMLEN(size
);
80 if ((err
= big_init(&(key
->p
), len
)) != BIG_OK
)
82 if ((err
= big_init(&(key
->g
), len
)) != BIG_OK
)
84 if ((err
= big_init(&(key
->x
), len
)) != BIG_OK
)
86 if ((err
= big_init(&(key
->y
), len
)) != BIG_OK
)
92 big_finish(&(key
->x
));
94 big_finish(&(key
->g
));
96 big_finish(&(key
->p
));
101 DH_key_finish(DHkey
*key
)
104 big_finish(&(key
->y
));
105 big_finish(&(key
->x
));
106 big_finish(&(key
->g
));
107 big_finish(&(key
->p
));
112 * Generate DH key pair x and y, given prime p and base g.
113 * Can optionally provided bit length of x, not to exceed bit length of p.
115 * For those not familiar with DH keys, there are 4 components:
117 * g - the base 0 < g < p
118 * x - a random number 0 < x < p-1, or if a smaller value is desired,
119 * 2^(len-1) <= x < 2^(len)
120 * y = g^x mod p, this implies 0 < y < p. That is important!
123 dh_genkey_pair(DHbytekey
*bkey
)
127 uint32_t primebit_len
;
129 int (*rf
)(void *, size_t);
130 uint32_t prime_bytes
;
133 return (CKR_ARGUMENTS_BAD
);
135 /* Must have prime and base set, value bits can be 0 or non-0 */
136 if (bkey
->prime_bits
== 0 || bkey
->prime
== NULL
||
137 bkey
->base_bytes
== 0 || bkey
->base
== NULL
)
138 return (CKR_ARGUMENTS_BAD
);
140 prime_bytes
= CRYPTO_BITS2BYTES(bkey
->prime_bits
);
142 if ((prime_bytes
< MIN_DH_KEYLENGTH_IN_BYTES
) ||
143 (prime_bytes
> MAX_DH_KEYLENGTH_IN_BYTES
)) {
144 return (CKR_KEY_SIZE_RANGE
);
148 * Initialize the DH key.
149 * Note: big_extend takes length in words.
151 if ((brv
= DH_key_init(&dhkey
, bkey
->prime_bits
)) != BIG_OK
) {
152 rv
= convert_rv(brv
);
156 /* Convert prime p to bignum. */
157 if ((brv
= big_extend(&(dhkey
.p
), CHARLEN2BIGNUMLEN(prime_bytes
))) !=
159 rv
= convert_rv(brv
);
162 bytestring2bignum(&(dhkey
.p
), bkey
->prime
, prime_bytes
);
164 /* Convert base g to bignum. */
165 if ((brv
= big_extend(&(dhkey
.g
),
166 CHARLEN2BIGNUMLEN(bkey
->base_bytes
))) != BIG_OK
) {
167 rv
= convert_rv(brv
);
170 bytestring2bignum(&(dhkey
.g
), bkey
->base
, bkey
->base_bytes
);
172 /* Base g cannot be greater than prime p. */
173 if (big_cmp_abs(&(dhkey
.g
), &(dhkey
.p
)) >= 0) {
174 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
179 * The intention of selecting a private-value length is to reduce
180 * the computation time for key agreement, while maintaining a
181 * given level of security.
184 /* Maximum bit length for private-value x is bit length of prime p */
185 primebit_len
= big_bitlength(&(dhkey
.p
));
187 if (bkey
->value_bits
== 0)
188 bkey
->value_bits
= primebit_len
;
190 if (bkey
->value_bits
> primebit_len
) {
191 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
195 /* Generate DH key pair private and public values. */
196 if ((brv
= big_extend(&(dhkey
.x
), BITLEN2BIGNUMLEN(bkey
->value_bits
)))
198 rv
= convert_rv(brv
);
202 if ((brv
= big_extend(&(dhkey
.y
), CHARLEN2BIGNUMLEN(prime_bytes
)))
204 rv
= convert_rv(brv
);
209 * The big integer of the private value shall be generated privately
215 rf
= random_get_pseudo_bytes
;
217 rf
= pkcs11_get_urandom
;
221 if ((brv
= big_random(&(dhkey
.x
), bkey
->value_bits
, rf
)) != BIG_OK
) {
222 rv
= convert_rv(brv
);
227 * The base g shall be raised to the private value x modulo p to
228 * give an integer y, the integer public value, i.e. y = (g^x) mod p.
230 if ((brv
= big_modexp(&(dhkey
.y
), &(dhkey
.g
), &(dhkey
.x
),
231 &(dhkey
.p
), NULL
)) != BIG_OK
) {
232 rv
= convert_rv(brv
);
236 bignum2bytestring(bkey
->private_x
, &(dhkey
.x
),
237 CRYPTO_BITS2BYTES(bkey
->value_bits
));
238 bignum2bytestring(bkey
->public_y
, &(dhkey
.y
), prime_bytes
);
241 DH_key_finish(&dhkey
);
247 * DH key derive operation, flag is ignored in userland
250 dh_key_derive(DHbytekey
*bkey
, uint32_t key_type
, /* = CKK_KEY_TYPE */
251 uchar_t
*secretkey
, uint32_t *secretkey_len
, /* derived secret */
258 uint32_t s_bytes
= 0;
259 uint32_t prime_bytes
;
260 uint32_t value_bytes
;
264 return (CKR_ARGUMENTS_BAD
);
266 /* Must have prime, private value and public value */
267 if (bkey
->prime_bits
== 0 || bkey
->prime
== NULL
||
268 bkey
->value_bits
== 0 || bkey
->private_x
== NULL
||
269 bkey
->public_y
== NULL
)
270 return (CKR_ARGUMENTS_BAD
);
272 if (secretkey
== NULL
) {
273 return (CKR_ARGUMENTS_BAD
);
276 prime_bytes
= CRYPTO_BITS2BYTES(bkey
->prime_bits
);
277 value_bytes
= CRYPTO_BITS2BYTES(bkey
->value_bits
);
280 * Initialize the DH key.
281 * Note: big_extend takes length in words.
283 if ((brv
= DH_key_init(&dhkey
, bkey
->prime_bits
)) != BIG_OK
) {
284 rv
= convert_rv(brv
);
288 /* Convert prime p to bignum. */
289 if ((brv
= big_extend(&(dhkey
.p
), CHARLEN2BIGNUMLEN(prime_bytes
))) !=
291 rv
= convert_rv(brv
);
294 bytestring2bignum(&(dhkey
.p
), bkey
->prime
, prime_bytes
);
296 /* Convert private-value x to bignum. */
297 if ((brv
= big_extend(&(dhkey
.x
), CHARLEN2BIGNUMLEN(value_bytes
))) !=
299 rv
= convert_rv(brv
);
302 bytestring2bignum(&(dhkey
.x
), bkey
->private_x
, value_bytes
);
304 /* Convert public-value y to bignum. */
305 if ((brv
= big_extend(&(dhkey
.y
), CHARLEN2BIGNUMLEN(prime_bytes
))) !=
307 rv
= convert_rv(brv
);
310 bytestring2bignum(&(dhkey
.y
), bkey
->public_y
, prime_bytes
);
313 * Recycle base g as a temporary variable to compute the derived
314 * secret value which is "g" = (y^x) mod p. (Not recomputing g.)
316 if ((brv
= big_extend(&(dhkey
.g
), CHARLEN2BIGNUMLEN(prime_bytes
))) !=
318 rv
= convert_rv(brv
);
322 if ((brv
= big_modexp(&(dhkey
.g
), &(dhkey
.y
), &(dhkey
.x
),
323 &(dhkey
.p
), NULL
)) != BIG_OK
) {
324 rv
= convert_rv(brv
);
328 s_alloc
= P2ROUNDUP_TYPED(prime_bytes
, sizeof (BIG_CHUNK_TYPE
), size_t);
331 if ((s
= kmem_alloc(s_alloc
, flag
)) == NULL
) {
332 rv
= CKR_HOST_MEMORY
;
336 if ((s
= malloc(s_alloc
)) == NULL
) {
337 rv
= CKR_HOST_MEMORY
;
341 s_bytes
= dhkey
.g
.len
* (int)sizeof (BIG_CHUNK_TYPE
);
342 bignum2bytestring(s
, &(dhkey
.g
), s_bytes
);
347 *secretkey_len
= DES_KEYSIZE
;
350 *secretkey_len
= DES2_KEYSIZE
;
353 *secretkey_len
= DES3_KEYSIZE
;
357 case CKK_GENERIC_SECRET
:
358 /* use provided secret key length, if any */
361 /* invalid key type */
362 rv
= CKR_ATTRIBUTE_TYPE_INVALID
;
366 if (*secretkey_len
== 0) {
367 *secretkey_len
= s_bytes
;
370 if (*secretkey_len
> s_bytes
) {
371 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
376 * The truncation removes bytes from the leading end of the
379 (void) memcpy(secretkey
, (s
+ s_bytes
- *secretkey_len
),
385 kmem_free(s
, s_alloc
);
390 DH_key_finish(&dhkey
);