1*12573SDina.Nimeh@Sun.COM /*
2*12573SDina.Nimeh@Sun.COM * CDDL HEADER START
3*12573SDina.Nimeh@Sun.COM *
4*12573SDina.Nimeh@Sun.COM * The contents of this file are subject to the terms of the
5*12573SDina.Nimeh@Sun.COM * Common Development and Distribution License (the "License").
6*12573SDina.Nimeh@Sun.COM * You may not use this file except in compliance with the License.
7*12573SDina.Nimeh@Sun.COM *
8*12573SDina.Nimeh@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12573SDina.Nimeh@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*12573SDina.Nimeh@Sun.COM * See the License for the specific language governing permissions
11*12573SDina.Nimeh@Sun.COM * and limitations under the License.
12*12573SDina.Nimeh@Sun.COM *
13*12573SDina.Nimeh@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*12573SDina.Nimeh@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12573SDina.Nimeh@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*12573SDina.Nimeh@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*12573SDina.Nimeh@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*12573SDina.Nimeh@Sun.COM *
19*12573SDina.Nimeh@Sun.COM * CDDL HEADER END
20*12573SDina.Nimeh@Sun.COM */
21*12573SDina.Nimeh@Sun.COM
22*12573SDina.Nimeh@Sun.COM /*
23*12573SDina.Nimeh@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*12573SDina.Nimeh@Sun.COM */
25*12573SDina.Nimeh@Sun.COM
26*12573SDina.Nimeh@Sun.COM /*
27*12573SDina.Nimeh@Sun.COM * This file contains DH helper routines common to
28*12573SDina.Nimeh@Sun.COM * the PKCS11 soft token code and the kernel DH code.
29*12573SDina.Nimeh@Sun.COM */
30*12573SDina.Nimeh@Sun.COM
31*12573SDina.Nimeh@Sun.COM #include <sys/types.h>
32*12573SDina.Nimeh@Sun.COM #include <sys/sysmacros.h>
33*12573SDina.Nimeh@Sun.COM #include <bignum.h>
34*12573SDina.Nimeh@Sun.COM
35*12573SDina.Nimeh@Sun.COM #ifdef _KERNEL
36*12573SDina.Nimeh@Sun.COM #include <sys/param.h>
37*12573SDina.Nimeh@Sun.COM #else
38*12573SDina.Nimeh@Sun.COM #include <strings.h>
39*12573SDina.Nimeh@Sun.COM #include <cryptoutil.h>
40*12573SDina.Nimeh@Sun.COM #endif
41*12573SDina.Nimeh@Sun.COM
42*12573SDina.Nimeh@Sun.COM #include <sys/crypto/common.h>
43*12573SDina.Nimeh@Sun.COM #include <des/des_impl.h>
44*12573SDina.Nimeh@Sun.COM #include "dh_impl.h"
45*12573SDina.Nimeh@Sun.COM
46*12573SDina.Nimeh@Sun.COM
47*12573SDina.Nimeh@Sun.COM static CK_RV
convert_rv(BIG_ERR_CODE err)48*12573SDina.Nimeh@Sun.COM convert_rv(BIG_ERR_CODE err)
49*12573SDina.Nimeh@Sun.COM {
50*12573SDina.Nimeh@Sun.COM switch (err) {
51*12573SDina.Nimeh@Sun.COM
52*12573SDina.Nimeh@Sun.COM case BIG_OK:
53*12573SDina.Nimeh@Sun.COM return (CKR_OK);
54*12573SDina.Nimeh@Sun.COM
55*12573SDina.Nimeh@Sun.COM case BIG_NO_MEM:
56*12573SDina.Nimeh@Sun.COM return (CKR_HOST_MEMORY);
57*12573SDina.Nimeh@Sun.COM
58*12573SDina.Nimeh@Sun.COM case BIG_NO_RANDOM:
59*12573SDina.Nimeh@Sun.COM return (CKR_DEVICE_ERROR);
60*12573SDina.Nimeh@Sun.COM
61*12573SDina.Nimeh@Sun.COM case BIG_INVALID_ARGS:
62*12573SDina.Nimeh@Sun.COM return (CKR_ARGUMENTS_BAD);
63*12573SDina.Nimeh@Sun.COM
64*12573SDina.Nimeh@Sun.COM case BIG_DIV_BY_0:
65*12573SDina.Nimeh@Sun.COM default:
66*12573SDina.Nimeh@Sun.COM return (CKR_GENERAL_ERROR);
67*12573SDina.Nimeh@Sun.COM }
68*12573SDina.Nimeh@Sun.COM }
69*12573SDina.Nimeh@Sun.COM
70*12573SDina.Nimeh@Sun.COM /* size is in bits */
71*12573SDina.Nimeh@Sun.COM static BIG_ERR_CODE
DH_key_init(DHkey * key,int size)72*12573SDina.Nimeh@Sun.COM DH_key_init(DHkey *key, int size)
73*12573SDina.Nimeh@Sun.COM {
74*12573SDina.Nimeh@Sun.COM BIG_ERR_CODE err = BIG_OK;
75*12573SDina.Nimeh@Sun.COM int len;
76*12573SDina.Nimeh@Sun.COM
77*12573SDina.Nimeh@Sun.COM len = BITLEN2BIGNUMLEN(size);
78*12573SDina.Nimeh@Sun.COM key->size = size;
79*12573SDina.Nimeh@Sun.COM
80*12573SDina.Nimeh@Sun.COM if ((err = big_init(&(key->p), len)) != BIG_OK)
81*12573SDina.Nimeh@Sun.COM return (err);
82*12573SDina.Nimeh@Sun.COM if ((err = big_init(&(key->g), len)) != BIG_OK)
83*12573SDina.Nimeh@Sun.COM goto ret1;
84*12573SDina.Nimeh@Sun.COM if ((err = big_init(&(key->x), len)) != BIG_OK)
85*12573SDina.Nimeh@Sun.COM goto ret2;
86*12573SDina.Nimeh@Sun.COM if ((err = big_init(&(key->y), len)) != BIG_OK)
87*12573SDina.Nimeh@Sun.COM goto ret3;
88*12573SDina.Nimeh@Sun.COM
89*12573SDina.Nimeh@Sun.COM return (BIG_OK);
90*12573SDina.Nimeh@Sun.COM
91*12573SDina.Nimeh@Sun.COM ret3:
92*12573SDina.Nimeh@Sun.COM big_finish(&(key->x));
93*12573SDina.Nimeh@Sun.COM ret2:
94*12573SDina.Nimeh@Sun.COM big_finish(&(key->g));
95*12573SDina.Nimeh@Sun.COM ret1:
96*12573SDina.Nimeh@Sun.COM big_finish(&(key->p));
97*12573SDina.Nimeh@Sun.COM return (err);
98*12573SDina.Nimeh@Sun.COM }
99*12573SDina.Nimeh@Sun.COM
100*12573SDina.Nimeh@Sun.COM static void
DH_key_finish(DHkey * key)101*12573SDina.Nimeh@Sun.COM DH_key_finish(DHkey *key)
102*12573SDina.Nimeh@Sun.COM {
103*12573SDina.Nimeh@Sun.COM
104*12573SDina.Nimeh@Sun.COM big_finish(&(key->y));
105*12573SDina.Nimeh@Sun.COM big_finish(&(key->x));
106*12573SDina.Nimeh@Sun.COM big_finish(&(key->g));
107*12573SDina.Nimeh@Sun.COM big_finish(&(key->p));
108*12573SDina.Nimeh@Sun.COM
109*12573SDina.Nimeh@Sun.COM }
110*12573SDina.Nimeh@Sun.COM
111*12573SDina.Nimeh@Sun.COM /*
112*12573SDina.Nimeh@Sun.COM * Generate DH key pair x and y, given prime p and base g.
113*12573SDina.Nimeh@Sun.COM * Can optionally provided bit length of x, not to exceed bit length of p.
114*12573SDina.Nimeh@Sun.COM */
115*12573SDina.Nimeh@Sun.COM CK_RV
dh_genkey_pair(DHbytekey * bkey)116*12573SDina.Nimeh@Sun.COM dh_genkey_pair(DHbytekey *bkey)
117*12573SDina.Nimeh@Sun.COM {
118*12573SDina.Nimeh@Sun.COM CK_RV rv = CKR_OK;
119*12573SDina.Nimeh@Sun.COM BIG_ERR_CODE brv;
120*12573SDina.Nimeh@Sun.COM uint32_t primebit_len;
121*12573SDina.Nimeh@Sun.COM DHkey dhkey;
122*12573SDina.Nimeh@Sun.COM int (*rf)(void *, size_t);
123*12573SDina.Nimeh@Sun.COM uint32_t prime_bytes;
124*12573SDina.Nimeh@Sun.COM
125*12573SDina.Nimeh@Sun.COM if (bkey == NULL)
126*12573SDina.Nimeh@Sun.COM return (CKR_ARGUMENTS_BAD);
127*12573SDina.Nimeh@Sun.COM
128*12573SDina.Nimeh@Sun.COM /* Must have prime and base set, value bits can be 0 or non-0 */
129*12573SDina.Nimeh@Sun.COM if (bkey->prime_bits == 0 || bkey->prime == NULL ||
130*12573SDina.Nimeh@Sun.COM bkey->base_bytes == 0 || bkey->base == NULL)
131*12573SDina.Nimeh@Sun.COM return (CKR_ARGUMENTS_BAD);
132*12573SDina.Nimeh@Sun.COM
133*12573SDina.Nimeh@Sun.COM prime_bytes = CRYPTO_BITS2BYTES(bkey->prime_bits);
134*12573SDina.Nimeh@Sun.COM
135*12573SDina.Nimeh@Sun.COM if ((prime_bytes < MIN_DH_KEYLENGTH_IN_BYTES) ||
136*12573SDina.Nimeh@Sun.COM (prime_bytes > MAX_DH_KEYLENGTH_IN_BYTES)) {
137*12573SDina.Nimeh@Sun.COM return (CKR_KEY_SIZE_RANGE);
138*12573SDina.Nimeh@Sun.COM }
139*12573SDina.Nimeh@Sun.COM
140*12573SDina.Nimeh@Sun.COM /*
141*12573SDina.Nimeh@Sun.COM * Initialize the DH key.
142*12573SDina.Nimeh@Sun.COM * Note: big_extend takes length in words.
143*12573SDina.Nimeh@Sun.COM */
144*12573SDina.Nimeh@Sun.COM if ((brv = DH_key_init(&dhkey, bkey->prime_bits)) != BIG_OK) {
145*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
146*12573SDina.Nimeh@Sun.COM goto ret;
147*12573SDina.Nimeh@Sun.COM }
148*12573SDina.Nimeh@Sun.COM
149*12573SDina.Nimeh@Sun.COM /* Convert prime p to bignum. */
150*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.p), CHARLEN2BIGNUMLEN(prime_bytes))) !=
151*12573SDina.Nimeh@Sun.COM BIG_OK) {
152*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
153*12573SDina.Nimeh@Sun.COM goto ret;
154*12573SDina.Nimeh@Sun.COM }
155*12573SDina.Nimeh@Sun.COM bytestring2bignum(&(dhkey.p), bkey->prime, prime_bytes);
156*12573SDina.Nimeh@Sun.COM
157*12573SDina.Nimeh@Sun.COM /* Convert base g to bignum. */
158*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.g),
159*12573SDina.Nimeh@Sun.COM CHARLEN2BIGNUMLEN(bkey->base_bytes))) != BIG_OK) {
160*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
161*12573SDina.Nimeh@Sun.COM goto ret;
162*12573SDina.Nimeh@Sun.COM }
163*12573SDina.Nimeh@Sun.COM bytestring2bignum(&(dhkey.g), bkey->base, bkey->base_bytes);
164*12573SDina.Nimeh@Sun.COM
165*12573SDina.Nimeh@Sun.COM /* Base g cannot be greater than prime p. */
166*12573SDina.Nimeh@Sun.COM if (big_cmp_abs(&(dhkey.g), &(dhkey.p)) >= 0) {
167*12573SDina.Nimeh@Sun.COM rv = CKR_ATTRIBUTE_VALUE_INVALID;
168*12573SDina.Nimeh@Sun.COM goto ret;
169*12573SDina.Nimeh@Sun.COM }
170*12573SDina.Nimeh@Sun.COM
171*12573SDina.Nimeh@Sun.COM /*
172*12573SDina.Nimeh@Sun.COM * The intention of selecting a private-value length is to reduce
173*12573SDina.Nimeh@Sun.COM * the computation time for key agreement, while maintaining a
174*12573SDina.Nimeh@Sun.COM * given level of security.
175*12573SDina.Nimeh@Sun.COM */
176*12573SDina.Nimeh@Sun.COM
177*12573SDina.Nimeh@Sun.COM /* Maximum bit length for private-value x is bit length of prime p */
178*12573SDina.Nimeh@Sun.COM primebit_len = big_bitlength(&(dhkey.p));
179*12573SDina.Nimeh@Sun.COM
180*12573SDina.Nimeh@Sun.COM if (bkey->value_bits == 0)
181*12573SDina.Nimeh@Sun.COM bkey->value_bits = primebit_len;
182*12573SDina.Nimeh@Sun.COM
183*12573SDina.Nimeh@Sun.COM if (bkey->value_bits > primebit_len) {
184*12573SDina.Nimeh@Sun.COM rv = CKR_ATTRIBUTE_VALUE_INVALID;
185*12573SDina.Nimeh@Sun.COM goto ret;
186*12573SDina.Nimeh@Sun.COM }
187*12573SDina.Nimeh@Sun.COM
188*12573SDina.Nimeh@Sun.COM /* Generate DH key pair private and public values. */
189*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.x), CHARLEN2BIGNUMLEN(prime_bytes)))
190*12573SDina.Nimeh@Sun.COM != BIG_OK) {
191*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
192*12573SDina.Nimeh@Sun.COM goto ret;
193*12573SDina.Nimeh@Sun.COM }
194*12573SDina.Nimeh@Sun.COM
195*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.y), CHARLEN2BIGNUMLEN(prime_bytes)))
196*12573SDina.Nimeh@Sun.COM != BIG_OK) {
197*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
198*12573SDina.Nimeh@Sun.COM goto ret;
199*12573SDina.Nimeh@Sun.COM }
200*12573SDina.Nimeh@Sun.COM
201*12573SDina.Nimeh@Sun.COM /*
202*12573SDina.Nimeh@Sun.COM * The big integer of the private value shall be generated privately
203*12573SDina.Nimeh@Sun.COM * and randomly.
204*12573SDina.Nimeh@Sun.COM */
205*12573SDina.Nimeh@Sun.COM rf = bkey->rfunc;
206*12573SDina.Nimeh@Sun.COM if (rf == NULL) {
207*12573SDina.Nimeh@Sun.COM #ifdef _KERNEL
208*12573SDina.Nimeh@Sun.COM rf = random_get_pseudo_bytes;
209*12573SDina.Nimeh@Sun.COM #else
210*12573SDina.Nimeh@Sun.COM rf = pkcs11_get_urandom;
211*12573SDina.Nimeh@Sun.COM #endif
212*12573SDina.Nimeh@Sun.COM }
213*12573SDina.Nimeh@Sun.COM
214*12573SDina.Nimeh@Sun.COM if ((brv = big_random(&(dhkey.x), bkey->value_bits, rf)) != BIG_OK) {
215*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
216*12573SDina.Nimeh@Sun.COM goto ret;
217*12573SDina.Nimeh@Sun.COM }
218*12573SDina.Nimeh@Sun.COM
219*12573SDina.Nimeh@Sun.COM /*
220*12573SDina.Nimeh@Sun.COM * The base g shall be raised to the private value x modulo p to
221*12573SDina.Nimeh@Sun.COM * give an integer y, the integer public value, i.e. y = (g^x) mod p.
222*12573SDina.Nimeh@Sun.COM */
223*12573SDina.Nimeh@Sun.COM if ((brv = big_modexp(&(dhkey.y), &(dhkey.g), &(dhkey.x),
224*12573SDina.Nimeh@Sun.COM &(dhkey.p), NULL)) != BIG_OK) {
225*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
226*12573SDina.Nimeh@Sun.COM goto ret;
227*12573SDina.Nimeh@Sun.COM }
228*12573SDina.Nimeh@Sun.COM
229*12573SDina.Nimeh@Sun.COM bignum2bytestring(bkey->private_x, &(dhkey.x), prime_bytes);
230*12573SDina.Nimeh@Sun.COM bignum2bytestring(bkey->public_y, &(dhkey.y), prime_bytes);
231*12573SDina.Nimeh@Sun.COM
232*12573SDina.Nimeh@Sun.COM ret:
233*12573SDina.Nimeh@Sun.COM DH_key_finish(&dhkey);
234*12573SDina.Nimeh@Sun.COM
235*12573SDina.Nimeh@Sun.COM return (rv);
236*12573SDina.Nimeh@Sun.COM }
237*12573SDina.Nimeh@Sun.COM
238*12573SDina.Nimeh@Sun.COM /*
239*12573SDina.Nimeh@Sun.COM * DH key derive operation
240*12573SDina.Nimeh@Sun.COM */
241*12573SDina.Nimeh@Sun.COM CK_RV
dh_key_derive(DHbytekey * bkey,uint32_t key_type,uchar_t * secretkey,uint32_t * secretkey_len)242*12573SDina.Nimeh@Sun.COM dh_key_derive(DHbytekey *bkey, uint32_t key_type, /* = CKK_KEY_TYPE */
243*12573SDina.Nimeh@Sun.COM uchar_t *secretkey, uint32_t *secretkey_len) /* derived secret */
244*12573SDina.Nimeh@Sun.COM {
245*12573SDina.Nimeh@Sun.COM CK_RV rv = CKR_OK;
246*12573SDina.Nimeh@Sun.COM BIG_ERR_CODE brv;
247*12573SDina.Nimeh@Sun.COM DHkey dhkey;
248*12573SDina.Nimeh@Sun.COM uchar_t *s = NULL;
249*12573SDina.Nimeh@Sun.COM uint32_t s_bytes = 0;
250*12573SDina.Nimeh@Sun.COM uint32_t prime_bytes;
251*12573SDina.Nimeh@Sun.COM uint32_t value_bytes;
252*12573SDina.Nimeh@Sun.COM
253*12573SDina.Nimeh@Sun.COM if (bkey == NULL)
254*12573SDina.Nimeh@Sun.COM return (CKR_ARGUMENTS_BAD);
255*12573SDina.Nimeh@Sun.COM
256*12573SDina.Nimeh@Sun.COM /* Must have prime, private value and public value */
257*12573SDina.Nimeh@Sun.COM if (bkey->prime_bits == 0 || bkey->prime == NULL ||
258*12573SDina.Nimeh@Sun.COM bkey->value_bits == 0 || bkey->private_x == NULL ||
259*12573SDina.Nimeh@Sun.COM bkey->public_y == NULL)
260*12573SDina.Nimeh@Sun.COM return (CKR_ARGUMENTS_BAD);
261*12573SDina.Nimeh@Sun.COM
262*12573SDina.Nimeh@Sun.COM if (secretkey == NULL) {
263*12573SDina.Nimeh@Sun.COM return (CKR_ARGUMENTS_BAD);
264*12573SDina.Nimeh@Sun.COM }
265*12573SDina.Nimeh@Sun.COM
266*12573SDina.Nimeh@Sun.COM prime_bytes = CRYPTO_BITS2BYTES(bkey->prime_bits);
267*12573SDina.Nimeh@Sun.COM value_bytes = CRYPTO_BITS2BYTES(bkey->value_bits);
268*12573SDina.Nimeh@Sun.COM
269*12573SDina.Nimeh@Sun.COM /*
270*12573SDina.Nimeh@Sun.COM * Initialize the DH key.
271*12573SDina.Nimeh@Sun.COM * Note: big_extend takes length in words.
272*12573SDina.Nimeh@Sun.COM */
273*12573SDina.Nimeh@Sun.COM if ((brv = DH_key_init(&dhkey, bkey->prime_bits)) != BIG_OK) {
274*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
275*12573SDina.Nimeh@Sun.COM goto ret;
276*12573SDina.Nimeh@Sun.COM }
277*12573SDina.Nimeh@Sun.COM
278*12573SDina.Nimeh@Sun.COM /* Convert prime p to bignum. */
279*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.p), CHARLEN2BIGNUMLEN(prime_bytes))) !=
280*12573SDina.Nimeh@Sun.COM BIG_OK) {
281*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
282*12573SDina.Nimeh@Sun.COM goto ret;
283*12573SDina.Nimeh@Sun.COM }
284*12573SDina.Nimeh@Sun.COM bytestring2bignum(&(dhkey.p), bkey->prime, prime_bytes);
285*12573SDina.Nimeh@Sun.COM
286*12573SDina.Nimeh@Sun.COM /* Convert private-value x to bignum. */
287*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.x), CHARLEN2BIGNUMLEN(value_bytes))) !=
288*12573SDina.Nimeh@Sun.COM BIG_OK) {
289*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
290*12573SDina.Nimeh@Sun.COM goto ret;
291*12573SDina.Nimeh@Sun.COM }
292*12573SDina.Nimeh@Sun.COM bytestring2bignum(&(dhkey.x), bkey->private_x, value_bytes);
293*12573SDina.Nimeh@Sun.COM
294*12573SDina.Nimeh@Sun.COM /* Convert public-value y to bignum. */
295*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.y), CHARLEN2BIGNUMLEN(value_bytes))) !=
296*12573SDina.Nimeh@Sun.COM BIG_OK) {
297*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
298*12573SDina.Nimeh@Sun.COM goto ret;
299*12573SDina.Nimeh@Sun.COM }
300*12573SDina.Nimeh@Sun.COM bytestring2bignum(&(dhkey.y), bkey->public_y, value_bytes);
301*12573SDina.Nimeh@Sun.COM
302*12573SDina.Nimeh@Sun.COM /*
303*12573SDina.Nimeh@Sun.COM * Recycle base g as a temporary variable to compute the derived
304*12573SDina.Nimeh@Sun.COM * secret value which is "g" = (y^x) mod p. (Not recomputing g.)
305*12573SDina.Nimeh@Sun.COM */
306*12573SDina.Nimeh@Sun.COM if ((brv = big_extend(&(dhkey.g), CHARLEN2BIGNUMLEN(prime_bytes))) !=
307*12573SDina.Nimeh@Sun.COM BIG_OK) {
308*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
309*12573SDina.Nimeh@Sun.COM goto ret;
310*12573SDina.Nimeh@Sun.COM }
311*12573SDina.Nimeh@Sun.COM
312*12573SDina.Nimeh@Sun.COM if ((brv = big_modexp(&(dhkey.g), &(dhkey.y), &(dhkey.x),
313*12573SDina.Nimeh@Sun.COM &(dhkey.p), NULL)) != BIG_OK) {
314*12573SDina.Nimeh@Sun.COM rv = convert_rv(brv);
315*12573SDina.Nimeh@Sun.COM goto ret;
316*12573SDina.Nimeh@Sun.COM }
317*12573SDina.Nimeh@Sun.COM
318*12573SDina.Nimeh@Sun.COM #ifdef _KERNEL
319*12573SDina.Nimeh@Sun.COM if ((s = kmem_alloc(P2ROUNDUP_TYPED(prime_bytes,
320*12573SDina.Nimeh@Sun.COM sizeof (BIG_CHUNK_SIZE), size_t))) == NULL) {
321*12573SDina.Nimeh@Sun.COM #else
322*12573SDina.Nimeh@Sun.COM if ((s = malloc(P2ROUNDUP_TYPED(prime_bytes,
323*12573SDina.Nimeh@Sun.COM sizeof (BIG_CHUNK_SIZE), size_t))) == NULL) {
324*12573SDina.Nimeh@Sun.COM #endif
325*12573SDina.Nimeh@Sun.COM rv = CKR_HOST_MEMORY;
326*12573SDina.Nimeh@Sun.COM goto ret;
327*12573SDina.Nimeh@Sun.COM }
328*12573SDina.Nimeh@Sun.COM s_bytes = dhkey.g.len * (int)sizeof (BIG_CHUNK_TYPE);
329*12573SDina.Nimeh@Sun.COM bignum2bytestring(s, &(dhkey.g), s_bytes);
330*12573SDina.Nimeh@Sun.COM
331*12573SDina.Nimeh@Sun.COM switch (key_type) {
332*12573SDina.Nimeh@Sun.COM
333*12573SDina.Nimeh@Sun.COM case CKK_DES:
334*12573SDina.Nimeh@Sun.COM *secretkey_len = DES_KEYSIZE;
335*12573SDina.Nimeh@Sun.COM break;
336*12573SDina.Nimeh@Sun.COM case CKK_DES2:
337*12573SDina.Nimeh@Sun.COM *secretkey_len = DES2_KEYSIZE;
338*12573SDina.Nimeh@Sun.COM break;
339*12573SDina.Nimeh@Sun.COM case CKK_DES3:
340*12573SDina.Nimeh@Sun.COM *secretkey_len = DES3_KEYSIZE;
341*12573SDina.Nimeh@Sun.COM break;
342*12573SDina.Nimeh@Sun.COM case CKK_RC4:
343*12573SDina.Nimeh@Sun.COM case CKK_AES:
344*12573SDina.Nimeh@Sun.COM case CKK_GENERIC_SECRET:
345*12573SDina.Nimeh@Sun.COM /* use provided secret key length, if any */
346*12573SDina.Nimeh@Sun.COM break;
347*12573SDina.Nimeh@Sun.COM default:
348*12573SDina.Nimeh@Sun.COM /* invalid key type */
349*12573SDina.Nimeh@Sun.COM rv = CKR_ATTRIBUTE_TYPE_INVALID;
350*12573SDina.Nimeh@Sun.COM goto ret;
351*12573SDina.Nimeh@Sun.COM }
352*12573SDina.Nimeh@Sun.COM
353*12573SDina.Nimeh@Sun.COM if (*secretkey_len == 0) {
354*12573SDina.Nimeh@Sun.COM *secretkey_len = s_bytes;
355*12573SDina.Nimeh@Sun.COM }
356*12573SDina.Nimeh@Sun.COM
357*12573SDina.Nimeh@Sun.COM if (*secretkey_len > s_bytes) {
358*12573SDina.Nimeh@Sun.COM rv = CKR_ATTRIBUTE_VALUE_INVALID;
359*12573SDina.Nimeh@Sun.COM goto ret;
360*12573SDina.Nimeh@Sun.COM }
361*12573SDina.Nimeh@Sun.COM
362*12573SDina.Nimeh@Sun.COM /*
363*12573SDina.Nimeh@Sun.COM * The truncation removes bytes from the leading end of the
364*12573SDina.Nimeh@Sun.COM * secret value.
365*12573SDina.Nimeh@Sun.COM */
366*12573SDina.Nimeh@Sun.COM (void) memcpy(secretkey, (s + s_bytes - *secretkey_len),
367*12573SDina.Nimeh@Sun.COM *secretkey_len);
368*12573SDina.Nimeh@Sun.COM
369*12573SDina.Nimeh@Sun.COM ret:
370*12573SDina.Nimeh@Sun.COM if (s != NULL)
371*12573SDina.Nimeh@Sun.COM #ifdef _KERNEL
372*12573SDina.Nimeh@Sun.COM kmem_free(s, sizeof (BIG_CHUNK_SIZE));
373*12573SDina.Nimeh@Sun.COM #else
374*12573SDina.Nimeh@Sun.COM free(s);
375*12573SDina.Nimeh@Sun.COM #endif
376*12573SDina.Nimeh@Sun.COM
377*12573SDina.Nimeh@Sun.COM DH_key_finish(&dhkey);
378*12573SDina.Nimeh@Sun.COM
379*12573SDina.Nimeh@Sun.COM return (rv);
380*12573SDina.Nimeh@Sun.COM }
381