xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_softtoken/common/softASN1.c (revision 753a6d457b330b1b29b2d3eefcd0831116ce950d)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <lber.h>
32 #include <security/cryptoki.h>
33 #include <rsa_impl.h>
34 #include "softDSA.h"
35 #include "softDH.h"
36 #include "softObject.h"
37 #include "softASN1.h"
38 
39 #define	OID_TAG			0x06
40 
41 #define	MAX_DH_KEY	(MAX_DH_KEYLENGTH >> 3)	/* bytes in a DH key */
42 static uchar_t	DH_OID[] = {
43 	/* DH key agreement OID:  1 . 2 . 840 . 113549 . 1 . 3 . 1 */
44 	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x03, 0x01
45 };
46 
47 #define	MAX_DH942_KEY	(MAX_DH_KEYLENGTH >> 3)	/* bytes in a DH X9.42 key */
48 static uchar_t	DH942_OID[] = {
49 	/* DH X9.42 OID:  1 . 2 . 840 . 10046 . 1  */
50 	0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x01
51 };
52 
53 #define	MAX_DSA_KEY	MAX_DSA_KEY_LEN 	/* bytes in a DSA key */
54 static uchar_t	DSA_OID[] = {
55 	/* DSA algorithm OID:  1 . 2 . 840 . 10040 . 4 . 1  */
56 	0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01
57 };
58 
59 #define	MAX_RSA_KEY	MAX_RSA_KEYLENGTH_IN_BYTES	/* bytes in RSA key */
60 static uchar_t	RSA_OID[] = {
61 	/* RSA algorithm OID:  1 . 2 . 840 . 113549 . 1 . 1 . 1 */
62 	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01
63 };
64 
65 
66 /*
67  * If the first bit of big integer is non-zero (i.e, first byte is
68  * 0x80 or greater), it may be interpreted as an ASN.1 negative number.
69  * Add one leading byte of zero-padding only in these cases to ensure
70  * it is treated as an unsigned integer.
71  */
72 static CK_RV
73 pad_bigint_attr(biginteger_t *src, biginteger_t *dst)
74 {
75 	int	padding;
76 
77 	/* Src and dst must already by previously allocated. */
78 	if (src == NULL || dst == NULL)
79 		return (CKR_HOST_MEMORY);
80 
81 	if (src->big_value_len == 0) {
82 		dst->big_value = NULL;
83 		dst->big_value_len = 0;
84 		return (CKR_OK);
85 	}
86 	/*
87 	 * Realloc() may free() or shrink previous memory location, so
88 	 * clear out potentially sensitive data before that happens.
89 	 */
90 	if (dst->big_value != NULL)
91 		(void) memset(dst->big_value, 0x0, dst->big_value_len);
92 
93 	padding = (src->big_value[0] < 0x80) ? 0 : 1;
94 	dst->big_value_len = src->big_value_len + padding;
95 
96 	dst->big_value = realloc(dst->big_value, dst->big_value_len);
97 	if (dst->big_value == NULL)
98 		return (CKR_HOST_MEMORY);
99 
100 	/* Set zero-pad at first byte, then append actual big_value. */
101 	dst->big_value[0] = 0x0;
102 	(void) memcpy(&(dst->big_value[padding]), src->big_value,
103 		src->big_value_len);
104 	return (CKR_OK);
105 }
106 
107 /*
108  * Sometimes there is one bytes of zero-padding, if a big integer may
109  * be interpreted as an ASN.1 negative number (i.e, the first bit is
110  * non-zero, the first byte is 0x80 or greater).  Remove first byte
111  * of zero-padding in those cases from the decoded octet strings.
112  */
113 static CK_RV
114 unpad_bigint_attr(biginteger_t src, biginteger_t *dst)
115 {
116 	int	offset;
117 
118 	if (dst == NULL)
119 		return (CKR_HOST_MEMORY);
120 
121 	if (src.big_value_len == 0) {
122 		dst->big_value = NULL;
123 		dst->big_value_len = 0;
124 		return (CKR_OK);
125 	}
126 
127 	offset = (src.big_value[0] == 0x00) ? 1 : 0;
128 	dst->big_value_len = src.big_value_len - offset;
129 
130 	/*
131 	 * Must allocate memory here because subsequent calls to
132 	 * copy_bigint_attr() just redirect pointer; it doesn't
133 	 * really copy the bigint like the function name implies.
134 	 */
135 	dst->big_value = malloc(dst->big_value_len);
136 	if (dst->big_value == NULL)
137 		return (CKR_HOST_MEMORY);
138 
139 	(void) memcpy(dst->big_value, &(src.big_value[offset]),
140 	    dst->big_value_len);
141 	return (CKR_OK);
142 }
143 
144 
145 /* Encode RSA private key in ASN.1 BER syntax. */
146 static CK_RV
147 rsa_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
148 {
149 	CK_RV		rv = CKR_OK;
150 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
151 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
152 	int		version = SOFT_ASN_VERSION;
153 	biginteger_t	tmp_pad = { NULL, 0 };
154 
155 	/*
156 	 * The ASN.1 syntax for an RSA private key is:
157 	 *
158 	 * PKCS#8	\* PrivateKeyInfo *\
159 	 * ---------------------------------
160 	 * Sequence {
161 	 *	version		INTEGER;
162 	 *	Sequence {	\* PrivateKeyAlgorithm *\
163 	 *		OID	0x06,	\* RSA algorithm OID *\
164 	 *		param(NULL)
165 	 *	}
166 	 *	RSAPrivateKey	OCTETSTRING =
167 	 *		PKCS#1	\* RSAPrivateKey *\
168 	 *		---------------------------
169 	 *		Sequence {
170 	 *			version		INTEGER,
171 	 *			modulus		INTEGER,
172 	 *			publicExponent	INTEGER,
173 	 *			privateExponent	INTEGER,
174 	 *			prime1		INTEGER,
175 	 *			prime2		INTEGER,
176 	 *			exponent1	INTEGER,
177 	 *			exponent2	INTEGER,
178 	 *			coefficient	INTEGER
179 	 *		}
180 	 * }
181 	 *
182 	 * The code below starts building the innermost octets
183 	 * RSAPrivateKey, and then builds the PrivateKeyInfo
184 	 * sequence around that octet string.  The BER syntax
185 	 * used in this function is (others may be possible):
186 	 *	{ i { to n } { i to  to  to  to  to  to  to  to } }
187 	 * where "i" is for integers with fixed size
188 	 * where "to" is for integers that vary in size (length + value)
189 	 * where "n" is for nulls
190 	 * where "{}" delimit sequences
191 	 */
192 
193 	/* RSAPrivateKey ... */
194 	if ((key_asn = ber_alloc()) == NULLBER)
195 		return (CKR_HOST_MEMORY);
196 
197 	/* ... begin-sequence { version, */
198 	if (ber_printf(key_asn, "{i", version) == -1) {
199 		rv = CKR_GENERAL_ERROR;
200 		goto cleanup_rsapri2asn;
201 	}
202 
203 	/* ... modulus, */
204 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_MOD(objp), &tmp_pad)) != CKR_OK)
205 		goto cleanup_rsapri2asn;
206 	if (ber_printf(key_asn, "to", LBER_INTEGER,
207 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
208 		rv = CKR_GENERAL_ERROR;
209 		goto cleanup_rsapri2asn;
210 	}
211 
212 	/* ... public exponent, */
213 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PUBEXPO(objp), &tmp_pad)) !=
214 	    CKR_OK)
215 		goto cleanup_rsapri2asn;
216 
217 	else if (ber_printf(key_asn, "to", LBER_INTEGER, tmp_pad.big_value,
218 	    tmp_pad.big_value_len) == -1) {
219 		rv = CKR_GENERAL_ERROR;
220 		goto cleanup_rsapri2asn;
221 	}
222 
223 	/* ... private exponent, */
224 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIEXPO(objp), &tmp_pad)) !=
225 	    CKR_OK)
226 		goto cleanup_rsapri2asn;
227 	if (ber_printf(key_asn, "to", LBER_INTEGER,
228 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
229 		rv = CKR_GENERAL_ERROR;
230 		goto cleanup_rsapri2asn;
231 	}
232 
233 	/* ... prime 1, */
234 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIME1(objp), &tmp_pad)) !=
235 	    CKR_OK)
236 		goto cleanup_rsapri2asn;
237 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
238 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
239 		rv = CKR_GENERAL_ERROR;
240 		goto cleanup_rsapri2asn;
241 	}
242 
243 	/* ... prime 2, */
244 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIME2(objp), &tmp_pad)) !=
245 	    CKR_OK)
246 		goto cleanup_rsapri2asn;
247 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
248 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
249 		rv = CKR_GENERAL_ERROR;
250 		goto cleanup_rsapri2asn;
251 	}
252 
253 	/* ... exponent 1, */
254 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_EXPO1(objp), &tmp_pad)) != CKR_OK)
255 		goto cleanup_rsapri2asn;
256 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
257 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
258 		rv = CKR_GENERAL_ERROR;
259 		goto cleanup_rsapri2asn;
260 	}
261 
262 	/* ... exponent 2, */
263 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_EXPO2(objp), &tmp_pad)) != CKR_OK)
264 		goto cleanup_rsapri2asn;
265 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
266 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
267 		rv = CKR_GENERAL_ERROR;
268 		goto cleanup_rsapri2asn;
269 	}
270 
271 	/* ... coeffient } end-sequence */
272 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_COEF(objp), &tmp_pad)) != CKR_OK)
273 		goto cleanup_rsapri2asn;
274 	else if (ber_printf(key_asn, "to}", LBER_INTEGER,
275 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
276 		rv = CKR_GENERAL_ERROR;
277 		goto cleanup_rsapri2asn;
278 	}
279 
280 	/* Convert key ASN.1 to octet string. */
281 	if (ber_flatten(key_asn, &key_octs) == -1) {
282 		rv = CKR_GENERAL_ERROR;
283 		goto cleanup_rsapri2asn;
284 	}
285 
286 	/* PKCS#8 PrivateKeyInfo ... */
287 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
288 		rv = CKR_HOST_MEMORY;
289 		goto cleanup_rsapri2asn;
290 	}
291 
292 	/*
293 	 * Embed key octet string into PKCS#8 object ASN.1:
294 	 * begin-sequence {
295 	 *	version
296 	 *	begin-sequence {
297 	 *		OID,
298 	 *		NULL
299 	 *	} end-sequence
300 	 *	RSAPrivateKey
301 	 * } end-sequence
302 	 */
303 	if (ber_printf(p8obj_asn, "{i{ton}o}", version,
304 	    OID_TAG, RSA_OID, sizeof (RSA_OID), /* NULL parameter, */
305 	    key_octs->bv_val, key_octs->bv_len) == -1) {
306 		rv = CKR_GENERAL_ERROR;
307 		goto cleanup_rsapri2asn;
308 	}
309 
310 	/* Convert PKCS#8 object ASN.1 to octet string. */
311 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
312 		rv = CKR_GENERAL_ERROR;
313 		goto cleanup_rsapri2asn;
314 	}
315 
316 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
317 	/*
318 	 * If the user passes in a null buf, then buf_len is set.
319 	 * If the user passes in a value with buf_len, then it can
320 	 * be checked to see if the accompanying buf is big enough.
321 	 * If it is, the octet string is copied into a pre-malloc'd
322 	 * buf; otherwise the user must resize buf and call again.
323 	 * In either case, buf_len is reset to the corrected size.
324 	 * See PKCS#11 section 11.2.
325 	 */
326 #ifdef _LP64
327 	/* LINTED E_CAST_INT_TO_SMALL_INT */
328 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
329 #else
330 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
331 #endif
332 		*buf_len = p8obj_octs->bv_len;
333 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
334 		goto cleanup_rsapri2asn;
335 	}
336 
337 	*buf_len = p8obj_octs->bv_len;
338 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
339 
340 cleanup_rsapri2asn:
341 
342 	if (tmp_pad.big_value != NULL) {
343 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
344 		free(tmp_pad.big_value);
345 	}
346 
347 	if (key_asn != NULLBER)
348 		ber_free(key_asn, 1);
349 
350 	if (key_octs != NULL)
351 		ber_bvfree(key_octs);
352 
353 	if (p8obj_asn != NULLBER)
354 		ber_free(p8obj_asn, 1);
355 
356 	if (p8obj_octs != NULL)
357 		ber_bvfree(p8obj_octs);
358 
359 	return (rv);
360 }
361 
362 /* Encode DSA private key in ASN.1 BER syntax. */
363 static CK_RV
364 dsa_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
365 {
366 	CK_RV		rv = CKR_OK;
367 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
368 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
369 	int		version = SOFT_ASN_VERSION;
370 	biginteger_t	tmp_pad = { NULL, 0 };
371 
372 	/*
373 	 * The ASN.1 syntax for a DSA private key is:
374 	 *
375 	 * PKCS#8	\* PrivateKeyInfo *\
376 	 * ---------------------------------
377 	 * Sequence {
378 	 *	version		INTEGER;
379 	 *	Sequence {	\* PrivateKeyAlgorithm *\
380 	 *		OID	0x06,	\* DSA algorithm OID *\
381 	 *		param(DSS-params)	OCTETSTRING =
382 	 *			PKCS#?	\* DSSParameter *\
383 	 *			----------------------------------
384 	 *			Sequence {
385 	 *				prime	INTEGER,
386 	 *				subprime INTEGER,
387 	 *				base	INTEGER,
388 	 *		}
389 	 *	}
390 	 *	DSAPrivateKey	OCTETSTRING =
391 	 *		PKCS#1	\* DSAPrivateKey *\
392 	 *		---------------------------
393 	 *		value		INTEGER
394 	 * }
395 	 *
396 	 * The code below starts building the innermost octets
397 	 * DSAPrivateKey, and then builds the PrivateKeyInfo
398 	 * sequence around that octet string.  The BER syntax
399 	 * used in this function is (others may be possible):
400 	 *	{ i { to { to to to } } to }
401 	 * where "i" is for integers with fixed size
402 	 * where "to" is for integers that vary in size (length + value)
403 	 * where "{}" delimit sequences
404 	 */
405 
406 	/* DSAPrivateKey ... */
407 	if ((key_asn = ber_alloc()) == NULLBER)
408 		return (CKR_HOST_MEMORY);
409 
410 	/* ... value */
411 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_VALUE(objp), &tmp_pad)) != CKR_OK)
412 		goto cleanup_dsapri2asn;
413 	if (ber_printf(key_asn, "to", LBER_INTEGER,
414 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
415 		rv = CKR_GENERAL_ERROR;
416 		goto cleanup_dsapri2asn;
417 	}
418 
419 	/* Convert key ASN.1 to octet string. */
420 	if (ber_flatten(key_asn, &key_octs) == -1) {
421 		rv = CKR_GENERAL_ERROR;
422 		goto cleanup_dsapri2asn;
423 	}
424 
425 	/* PKCS#8 PrivateKeyInfo ... */
426 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
427 		rv = CKR_HOST_MEMORY;
428 		goto cleanup_dsapri2asn;
429 	}
430 
431 	/*
432 	 * Start off the PKCS#8 object ASN.1:
433 	 * begin-sequence {
434 	 *	version
435 	 *	begin-sequence {
436 	 *		OID,
437 	 * ...
438 	 */
439 	if (ber_printf(p8obj_asn, "{i{to", version,
440 	    OID_TAG, DSA_OID, sizeof (DSA_OID)) == -1) {
441 		rv = CKR_GENERAL_ERROR;
442 		goto cleanup_dsapri2asn;
443 	}
444 
445 	/*
446 	 * Add DSS parameters:
447 	 * ...
448 	 *		begin-sequence {
449 	 *			prime,
450 	 * ...
451 	 */
452 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_PRIME(objp), &tmp_pad)) != CKR_OK)
453 		goto cleanup_dsapri2asn;
454 	if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
455 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
456 		rv = CKR_GENERAL_ERROR;
457 		goto cleanup_dsapri2asn;
458 	}
459 
460 	/*
461 	 * ...
462 	 *			subprime,
463 	 * ...
464 	 */
465 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_SUBPRIME(objp), &tmp_pad)) !=
466 	    CKR_OK)
467 		goto cleanup_dsapri2asn;
468 	if (ber_printf(p8obj_asn, "to", LBER_INTEGER,
469 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
470 		rv = CKR_GENERAL_ERROR;
471 		goto cleanup_dsapri2asn;
472 	}
473 
474 	/*
475 	 * ...
476 	 *			base
477 	 *		} end-sequence
478 	 */
479 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_BASE(objp), &tmp_pad)) != CKR_OK)
480 		goto cleanup_dsapri2asn;
481 	if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
482 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
483 		rv = CKR_GENERAL_ERROR;
484 		goto cleanup_dsapri2asn;
485 	}
486 
487 	/*
488 	 * Add the key octet string:
489 	 *	} end-sequence
490 	 *	DSAPrivateKey
491 	 * } end-sequence
492 	 */
493 	if (ber_printf(p8obj_asn, "}o}",
494 	    key_octs->bv_val, key_octs->bv_len) == -1) {
495 		rv = CKR_GENERAL_ERROR;
496 		goto cleanup_dsapri2asn;
497 	}
498 
499 	/* Convert PKCS#8 object ASN.1 to octet string. */
500 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
501 		rv = CKR_GENERAL_ERROR;
502 		goto cleanup_dsapri2asn;
503 	}
504 
505 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
506 	/*
507 	 * If the user passes in a null buf, then buf_len is set.
508 	 * If the user passes in a value with buf_len, then it can
509 	 * be checked to see if the accompanying buf is big enough.
510 	 * If it is, the octet string is copied into a pre-malloc'd
511 	 * buf; otherwise the user must resize buf and call again.
512 	 * In either case, buf_len is reset to the corrected size.
513 	 * See PKCS#11 section 11.2.
514 	 */
515 #ifdef _LP64
516 	/* LINTED E_CAST_INT_TO_SMALL_INT */
517 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
518 #else
519 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
520 #endif
521 		*buf_len = p8obj_octs->bv_len;
522 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
523 		goto cleanup_dsapri2asn;
524 	}
525 
526 	*buf_len = p8obj_octs->bv_len;
527 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
528 
529 cleanup_dsapri2asn:
530 
531 	if (tmp_pad.big_value != NULL) {
532 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
533 		free(tmp_pad.big_value);
534 	}
535 
536 	if (key_asn != NULLBER)
537 	    ber_free(key_asn, 1);
538 
539 	if (key_octs != NULL)
540 	    ber_bvfree(key_octs);
541 
542 	if (p8obj_asn != NULLBER)
543 	    ber_free(p8obj_asn, 1);
544 
545 	if (p8obj_octs != NULL)
546 	    ber_bvfree(p8obj_octs);
547 
548 	return (rv);
549 }
550 
551 /* Encode DH private key in ASN.1 BER syntax. */
552 static CK_RV
553 dh_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
554 {
555 	CK_RV		rv = CKR_OK;
556 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
557 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
558 	int		version = SOFT_ASN_VERSION;
559 	biginteger_t	tmp_pad = { NULL, 0 };
560 
561 	/*
562 	 * The ASN.1 syntax for a DH private key is:
563 	 *
564 	 * PKCS#8	\* PrivateKeyInfo *\
565 	 * ---------------------------------
566 	 * Sequence {
567 	 *	version		INTEGER;
568 	 *	Sequence {	\* PrivateKeyAlgorithm *\
569 	 *		OID	0x06,	\* DH algorithm OID *\
570 	 *		param(DH-params) OCTETSTRING =
571 	 *			PKCS#3	\* DHParameter *\
572 	 *			-------------------------
573 	 *			Sequence {
574 	 *				prime	INTEGER,
575 	 *				base	INTEGER
576 	 *			}
577 	 *	}
578 	 *	DHPrivateKey	OCTETSTRING =
579 	 *		PKCS#1	\* DHPrivateKey *\
580 	 *		--------------------------
581 	 *		value		INTEGER
582 	 * }
583 	 *
584 	 * The code below starts building the innermost octets
585 	 * DHPrivateKey, and then builds the PrivateKeyInfo
586 	 * sequence around that octet string.  The BER syntax
587 	 * used in this function is (others may be possible):
588 	 *	{ i { to { to to } } to }
589 	 * where "i" is for integers with fixed size
590 	 * where "to" is for integers that vary in size (length + value)
591 	 * where "{}" delimit sequences
592 	 */
593 
594 	/* DHPrivateKey ... */
595 	if ((key_asn = ber_alloc()) == NULLBER)
596 		return (CKR_HOST_MEMORY);
597 
598 	/* ... value */
599 	if ((rv = pad_bigint_attr(OBJ_PRI_DH_VALUE(objp), &tmp_pad)) != CKR_OK)
600 		goto cleanup_dhpri2asn;
601 	if (ber_printf(key_asn, "to", LBER_INTEGER,
602 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
603 		rv = CKR_GENERAL_ERROR;
604 		goto cleanup_dhpri2asn;
605 	}
606 
607 	/* Convert key ASN.1 to octet string. */
608 	if (ber_flatten(key_asn, &key_octs) == -1) {
609 		rv = CKR_GENERAL_ERROR;
610 		goto cleanup_dhpri2asn;
611 	}
612 
613 	/* PKCS#8 PrivateKeyInfo ... */
614 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
615 		rv = CKR_HOST_MEMORY;
616 		goto cleanup_dhpri2asn;
617 	}
618 
619 	/*
620 	 * Start off the PKCS#8 object ASN.1:
621 	 * begin-sequence {
622 	 *	version
623 	 *	begin-sequence {
624 	 *		OID,
625 	 * ...
626 	 */
627 	if (ber_printf(p8obj_asn, "{i{to", version,
628 	    OID_TAG, DH_OID, sizeof (DH_OID)) == -1) {
629 		rv = CKR_GENERAL_ERROR;
630 		goto cleanup_dhpri2asn;
631 	}
632 
633 	/*
634 	 * Add DH parameters:
635 	 * ...
636 	 *		begin-sequence {
637 	 *			prime,
638 	 * ...
639 	 */
640 	if ((rv = pad_bigint_attr(OBJ_PRI_DH_PRIME(objp), &tmp_pad)) != CKR_OK)
641 		goto cleanup_dhpri2asn;
642 	if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
643 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
644 		rv = CKR_GENERAL_ERROR;
645 		goto cleanup_dhpri2asn;
646 	}
647 
648 	/*
649 	 * ...
650 	 *			base
651 	 *		} end-sequence
652 	 */
653 	if ((rv = pad_bigint_attr(OBJ_PRI_DH_BASE(objp), &tmp_pad)) != CKR_OK)
654 		goto cleanup_dhpri2asn;
655 	if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
656 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
657 		rv = CKR_GENERAL_ERROR;
658 		goto cleanup_dhpri2asn;
659 	}
660 
661 	/*
662 	 * Add the key octet string:
663 	 *	} end-sequence
664 	 *	DSAPrivateKey
665 	 * } end-sequence
666 	 */
667 	if (ber_printf(p8obj_asn, "}o}",
668 	    key_octs->bv_val, key_octs->bv_len) == -1) {
669 		rv = CKR_GENERAL_ERROR;
670 		goto cleanup_dhpri2asn;
671 	}
672 
673 	/* Convert PKCS#8 object ASN.1 to octet string. */
674 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
675 		rv = CKR_GENERAL_ERROR;
676 		goto cleanup_dhpri2asn;
677 	}
678 
679 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
680 	/*
681 	 * If the user passes in a null buf, then buf_len is set.
682 	 * If the user passes in a value with buf_len, then it can
683 	 * be checked to see if the accompanying buf is big enough.
684 	 * If it is, the octet string is copied into a pre-malloc'd
685 	 * buf; otherwise the user must resize buf and call again.
686 	 * In either case, buf_len is reset to the corrected size.
687 	 * See PKCS#11 section 11.2.
688 	 */
689 #ifdef _LP64
690 	/* LINTED E_CAST_INT_TO_SMALL_INT */
691 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
692 #else
693 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
694 #endif
695 		*buf_len = p8obj_octs->bv_len;
696 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
697 		goto cleanup_dhpri2asn;
698 	}
699 
700 	*buf_len = p8obj_octs->bv_len;
701 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
702 
703 cleanup_dhpri2asn:
704 
705 	if (tmp_pad.big_value != NULL) {
706 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
707 		free(tmp_pad.big_value);
708 	}
709 
710 	if (key_asn != NULLBER)
711 	    ber_free(key_asn, 1);
712 
713 	if (key_octs != NULL)
714 	    ber_bvfree(key_octs);
715 
716 	if (p8obj_asn != NULLBER)
717 	    ber_free(p8obj_asn, 1);
718 
719 	if (p8obj_octs != NULL)
720 	    ber_bvfree(p8obj_octs);
721 
722 	return (rv);
723 }
724 
725 /* Encode DH X9.42 private key in ASN.1 BER syntax. */
726 static CK_RV
727 x942_dh_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
728 {
729 	CK_RV		rv = CKR_OK;
730 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
731 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
732 	int		version = SOFT_ASN_VERSION;
733 	biginteger_t	tmp_pad = { NULL, 0 };
734 
735 	/*
736 	 * The ASN.1 syntax for a X9.42 DH private key is:
737 	 *
738 	 * PKCS#8	\* PrivateKeyInfo *\
739 	 * ---------------------------------
740 	 * Sequence {
741 	 *	version		INTEGER;
742 	 *	Sequence {	\* PrivateKeyAlgorithm *\
743 	 *		OID	0x06,	\* DH X9.42 algorithm OID *\
744 	 *		param(DH-params) OCTETSTRING =
745 	 *			PKCS#3	\* DHParameter *\
746 	 *			-------------------------
747 	 *			Sequence {
748 	 *				prime	INTEGER,
749 	 *				base	INTEGER,
750 	 *				subprime INTEGER \* for X9.42 *\
751 	 *			}
752 	 *	}
753 	 *	DHPrivateKey	OCTETSTRING =
754 	 *		PKCS#1	\* DHPrivateKey *\
755 	 *		--------------------------
756 	 *		value		INTEGER
757 	 * }
758 	 *
759 	 * The code below starts building the innermost octets
760 	 * DHPrivateKey, and then builds the PrivateKeyInfo
761 	 * sequence around that octet string.  The BER syntax
762 	 * used in this function is (others may be possible):
763 	 *	{ i { to { to to } } to }
764 	 * where "i" is for integers with fixed size
765 	 * where "to" is for integers that vary in size (length + value)
766 	 * where "{}" delimit sequences
767 	 */
768 
769 	/* DHPrivateKey ... */
770 	if ((key_asn = ber_alloc()) == NULLBER)
771 		return (CKR_HOST_MEMORY);
772 
773 	/* ... value */
774 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_VALUE(objp), &tmp_pad)) !=
775 	    CKR_OK)
776 		goto cleanup_x942dhpri2asn;
777 	if (ber_printf(key_asn, "to", LBER_INTEGER,
778 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
779 		rv = CKR_GENERAL_ERROR;
780 		goto cleanup_x942dhpri2asn;
781 	}
782 
783 	/* Convert key ASN.1 to octet string. */
784 	if (ber_flatten(key_asn, &key_octs) == -1) {
785 		rv = CKR_GENERAL_ERROR;
786 		goto cleanup_x942dhpri2asn;
787 	}
788 
789 	/* PKCS#8 PrivateKeyInfo ... */
790 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
791 		rv = CKR_HOST_MEMORY;
792 		goto cleanup_x942dhpri2asn;
793 	}
794 
795 	/*
796 	 * Start off the PKCS#8 object ASN.1:
797 	 * begin-sequence {
798 	 *	version
799 	 *	begin-sequence {
800 	 *		OID,
801 	 * ...
802 	 */
803 	if (ber_printf(p8obj_asn, "{i{to", version,
804 	    OID_TAG, DH942_OID, sizeof (DH942_OID)) == -1) {
805 		rv = CKR_GENERAL_ERROR;
806 		goto cleanup_x942dhpri2asn;
807 	}
808 
809 	/*
810 	 * Add DH parameters:
811 	 * ...
812 	 *		begin-sequence {
813 	 *			prime,
814 	 * ...
815 	 */
816 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_PRIME(objp), &tmp_pad)) !=
817 	    CKR_OK)
818 		goto cleanup_x942dhpri2asn;
819 	if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
820 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
821 		rv = CKR_GENERAL_ERROR;
822 		goto cleanup_x942dhpri2asn;
823 	}
824 
825 	/*
826 	 * ...
827 	 *			base,
828 	 * ...
829 	 */
830 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_BASE(objp), &tmp_pad)) !=
831 	    CKR_OK)
832 		goto cleanup_x942dhpri2asn;
833 	if (ber_printf(p8obj_asn, "to", LBER_INTEGER,
834 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
835 		rv = CKR_GENERAL_ERROR;
836 		goto cleanup_x942dhpri2asn;
837 	}
838 
839 	/*
840 	 * ...
841 	 *			subprime
842 	 *		} end-sequence
843 	 */
844 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_SUBPRIME(objp), &tmp_pad)) !=
845 	    CKR_OK)
846 		goto cleanup_x942dhpri2asn;
847 	if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
848 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
849 		rv = CKR_GENERAL_ERROR;
850 		goto cleanup_x942dhpri2asn;
851 	}
852 
853 	/*
854 	 * Add the key octet string:
855 	 *	} end-sequence
856 	 *	DHPrivateKey
857 	 * } end-sequence
858 	 */
859 	if (ber_printf(p8obj_asn, "}o}",
860 	    key_octs->bv_val, key_octs->bv_len) == -1) {
861 		rv = CKR_GENERAL_ERROR;
862 		goto cleanup_x942dhpri2asn;
863 	}
864 
865 	/* Convert PKCS#8 object ASN.1 to octet string. */
866 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
867 		rv = CKR_GENERAL_ERROR;
868 		goto cleanup_x942dhpri2asn;
869 	}
870 
871 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
872 	/*
873 	 * If the user passes in a null buf, then buf_len is set.
874 	 * If the user passes in a value with buf_len, then it can
875 	 * be checked to see if the accompanying buf is big enough.
876 	 * If it is, the octet string is copied into a pre-malloc'd
877 	 * buf; otherwise the user must resize buf and call again.
878 	 * In either case, buf_len is reset to the corrected size.
879 	 * See PKCS#11 section 11.2.
880 	 */
881 #ifdef _LP64
882 	/* LINTED E_CAST_INT_TO_SMALL_INT */
883 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
884 #else
885 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
886 #endif
887 		*buf_len = p8obj_octs->bv_len;
888 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
889 		goto cleanup_x942dhpri2asn;
890 	}
891 
892 	*buf_len = p8obj_octs->bv_len;
893 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
894 
895 cleanup_x942dhpri2asn:
896 
897 	if (tmp_pad.big_value != NULL) {
898 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
899 		free(tmp_pad.big_value);
900 	}
901 
902 	if (key_asn != NULLBER)
903 	    ber_free(key_asn, 1);
904 
905 	if (key_octs != NULL)
906 	    ber_bvfree(key_octs);
907 
908 	if (p8obj_asn != NULLBER)
909 	    ber_free(p8obj_asn, 1);
910 
911 	if (p8obj_octs != NULL)
912 	    ber_bvfree(p8obj_octs);
913 
914 	return (rv);
915 }
916 
917 /*
918  * Encode the object key from the soft_object_t into ASN.1 format.
919  */
920 CK_RV
921 soft_object_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
922 {
923 	CK_OBJECT_CLASS class = objp->class;
924 	CK_KEY_TYPE	keytype = objp->key_type;
925 
926 	switch (class) {
927 
928 	case CKO_PRIVATE_KEY:
929 		switch (keytype) {
930 		case CKK_RSA:
931 			return (rsa_pri_to_asn1(objp, buf, buf_len));
932 
933 		case CKK_DSA:
934 			return (dsa_pri_to_asn1(objp, buf, buf_len));
935 
936 		case CKK_DH:
937 			return (dh_pri_to_asn1(objp, buf, buf_len));
938 
939 		case CKK_X9_42_DH:
940 			return (x942_dh_pri_to_asn1(objp, buf, buf_len));
941 
942 		default:
943 			return (CKR_FUNCTION_NOT_SUPPORTED);
944 		} /* keytype */
945 
946 		break;
947 
948 	default:
949 		return (CKR_FUNCTION_NOT_SUPPORTED);
950 
951 	} /* class */
952 }
953 
954 /* Decode ASN.1 BER syntax into RSA private key. */
955 static CK_RV
956 asn1_to_rsa_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
957 {
958 	CK_RV		rv = CKR_OK;
959 	BerValue	p8obj_octs, key_octs;
960 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
961 	ber_len_t	size, tmplen;
962 	char		*cookie;
963 	int		version;
964 	uchar_t		oid[sizeof (RSA_OID) + 1];
965 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
966 
967 	p8obj_octs.bv_val = (char *)buf;
968 #ifdef _LP64
969 	/* LINTED E_CAST_INT_TO_SMALL_INT */
970 	p8obj_octs.bv_len = (ber_len_t)buf_len;
971 #else
972 	p8obj_octs.bv_len = (ber_len_t)buf_len;
973 #endif
974 
975 	key_octs.bv_val = NULL;
976 	key_octs.bv_len = 0;
977 
978 	/* Decode PKCS#8 object ASN.1, verifying it is RSA private key. */
979 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
980 		return (CKR_GENERAL_ERROR);
981 
982 	/* PKCS#8 PrivateKeyInfo ... */
983 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
984 		rv = CKR_WRAPPED_KEY_INVALID;
985 		goto cleanup_asn2rsapri;
986 	}
987 	/* ... begin-sequence { version, */
988 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
989 
990 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
991 		rv = CKR_WRAPPED_KEY_INVALID;
992 		goto cleanup_asn2rsapri;
993 	}
994 	/* ... begin-sequence { */
995 	(void) ber_scanf(p8obj_asn, "{");
996 
997 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
998 		rv = CKR_WRAPPED_KEY_INVALID;
999 		goto cleanup_asn2rsapri;
1000 	}
1001 	/* ... OID, \* RSA algorithm OID *\ */
1002 	if (size != sizeof (RSA_OID)) {
1003 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1004 		goto cleanup_asn2rsapri;
1005 	}
1006 	size = sizeof (oid);
1007 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
1008 	if (memcmp(oid, RSA_OID, size) != 0) {
1009 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1010 		goto cleanup_asn2rsapri;
1011 	}
1012 
1013 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_NULL) {
1014 		rv = CKR_WRAPPED_KEY_INVALID;
1015 		goto cleanup_asn2rsapri;
1016 	}
1017 	/* ... param(NULL) } end-sequence */
1018 	(void) ber_scanf(p8obj_asn, "n");		/* "n}" ? */
1019 
1020 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1021 		rv = CKR_WRAPPED_KEY_INVALID;
1022 		goto cleanup_asn2rsapri;
1023 	}
1024 	/* ... RSAPrivateKey } end-sequence */
1025 	key_octs.bv_len = size + 1;
1026 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1027 		rv = CKR_HOST_MEMORY;
1028 		goto cleanup_asn2rsapri;
1029 	}
1030 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
1031 	    key_octs.bv_val, &key_octs.bv_len);
1032 
1033 	/* Decode key octet string into softtoken key object. */
1034 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1035 		rv = CKR_GENERAL_ERROR;
1036 		goto cleanup_asn2rsapri;
1037 	}
1038 
1039 	/* ... begin-sequence { version, */
1040 	if (ber_first_element(key_asn, &size, &cookie) != LBER_INTEGER) {
1041 		rv = CKR_WRAPPED_KEY_INVALID;
1042 		goto cleanup_asn2rsapri;
1043 	}
1044 	(void) ber_scanf(key_asn, "i", &version);	/* "{i" ? */
1045 
1046 	/* ... modulus, */
1047 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1048 		rv = CKR_WRAPPED_KEY_INVALID;
1049 		goto cleanup_asn2rsapri;
1050 	}
1051 	if (size > MAX_RSA_KEY) {
1052 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1053 		goto cleanup_asn2rsapri;
1054 	}
1055 	tmplen = size + 1;
1056 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1057 		rv = CKR_HOST_MEMORY;
1058 		goto cleanup_asn2rsapri;
1059 	}
1060 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1061 	tmp.big_value_len = tmplen;
1062 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1063 		free(tmp.big_value);
1064 		goto cleanup_asn2rsapri;
1065 	}
1066 	free(tmp.big_value);
1067 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_MOD(keyp));
1068 
1069 	/* ... public exponent, */
1070 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1071 		rv = CKR_WRAPPED_KEY_INVALID;
1072 		goto error_asn2rsapri;
1073 	}
1074 	if (size > MAX_RSA_KEY) {
1075 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1076 		goto error_asn2rsapri;
1077 	}
1078 	tmplen = size + 1;
1079 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1080 		rv = CKR_HOST_MEMORY;
1081 		goto error_asn2rsapri;
1082 	}
1083 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1084 	tmp.big_value_len = tmplen;
1085 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1086 		free(tmp.big_value);
1087 		goto error_asn2rsapri;
1088 	}
1089 	free(tmp.big_value);
1090 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PUBEXPO(keyp));
1091 
1092 	/* ... private exponent, */
1093 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1094 		rv = CKR_WRAPPED_KEY_INVALID;
1095 		goto error_asn2rsapri;
1096 	}
1097 	if (size > MAX_RSA_KEY) {
1098 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1099 		goto error_asn2rsapri;
1100 	}
1101 	tmplen = size + 1;
1102 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1103 		rv = CKR_HOST_MEMORY;
1104 		goto error_asn2rsapri;
1105 	}
1106 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1107 	tmp.big_value_len = tmplen;
1108 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1109 		free(tmp.big_value);
1110 		goto error_asn2rsapri;
1111 	}
1112 	free(tmp.big_value);
1113 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIEXPO(keyp));
1114 
1115 	/* ... prime 1, */
1116 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1117 		rv = CKR_WRAPPED_KEY_INVALID;
1118 		goto error_asn2rsapri;
1119 	}
1120 	if (size > MAX_RSA_KEY) {
1121 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1122 		goto error_asn2rsapri;
1123 	}
1124 	tmplen = size + 1;
1125 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1126 		rv = CKR_HOST_MEMORY;
1127 		goto error_asn2rsapri;
1128 	}
1129 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1130 	tmp.big_value_len = tmplen;
1131 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1132 		free(tmp.big_value);
1133 		goto error_asn2rsapri;
1134 	}
1135 	free(tmp.big_value);
1136 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIME1(keyp));
1137 
1138 	/* ... prime 2, */
1139 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1140 		rv = CKR_WRAPPED_KEY_INVALID;
1141 		goto error_asn2rsapri;
1142 	}
1143 	if (size > MAX_RSA_KEY) {
1144 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1145 		goto error_asn2rsapri;
1146 	}
1147 	tmplen = size + 1;
1148 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1149 		rv = CKR_HOST_MEMORY;
1150 		goto error_asn2rsapri;
1151 	}
1152 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1153 	tmp.big_value_len = tmplen;
1154 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1155 		free(tmp.big_value);
1156 		goto error_asn2rsapri;
1157 	}
1158 	free(tmp.big_value);
1159 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIME2(keyp));
1160 
1161 	/* ... exponent 1, */
1162 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1163 		rv = CKR_WRAPPED_KEY_INVALID;
1164 		goto error_asn2rsapri;
1165 	}
1166 	if (size > MAX_RSA_KEY) {
1167 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1168 		goto error_asn2rsapri;
1169 	}
1170 	tmplen = size + 1;
1171 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1172 		rv = CKR_HOST_MEMORY;
1173 		goto error_asn2rsapri;
1174 	}
1175 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1176 	tmp.big_value_len = tmplen;
1177 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1178 		free(tmp.big_value);
1179 		goto error_asn2rsapri;
1180 	}
1181 	free(tmp.big_value);
1182 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_EXPO1(keyp));
1183 
1184 	/* ... exponent 2, */
1185 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1186 		rv = CKR_WRAPPED_KEY_INVALID;
1187 		goto error_asn2rsapri;
1188 	}
1189 	if (size > MAX_RSA_KEY) {
1190 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1191 		goto error_asn2rsapri;
1192 	}
1193 	tmplen = size + 1;
1194 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1195 		rv = CKR_HOST_MEMORY;
1196 		goto error_asn2rsapri;
1197 	}
1198 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
1199 	tmp.big_value_len = tmplen;
1200 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1201 		free(tmp.big_value);
1202 		goto error_asn2rsapri;
1203 	}
1204 	free(tmp.big_value);
1205 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_EXPO2(keyp));
1206 
1207 	/* ... coefficient } end-sequence */
1208 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1209 		rv = CKR_WRAPPED_KEY_INVALID;
1210 		goto error_asn2rsapri;
1211 	}
1212 	if (size > MAX_RSA_KEY) {
1213 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1214 		goto error_asn2rsapri;
1215 	}
1216 	tmplen = size + 1;
1217 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1218 		rv = CKR_HOST_MEMORY;
1219 		goto error_asn2rsapri;
1220 	}
1221 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
1222 	    tmp.big_value, &tmplen);
1223 	tmp.big_value_len = tmplen;
1224 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1225 		free(tmp.big_value);
1226 		goto error_asn2rsapri;
1227 	}
1228 	free(tmp.big_value);
1229 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_COEF(keyp));
1230 
1231 	goto cleanup_asn2rsapri;
1232 
1233 error_asn2rsapri:
1234 
1235 	bigint_attr_cleanup(KEY_PRI_RSA_MOD(keyp));
1236 	bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(keyp));
1237 	bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(keyp));
1238 	bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(keyp));
1239 	bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(keyp));
1240 	bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(keyp));
1241 	bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(keyp));
1242 	bigint_attr_cleanup(KEY_PRI_RSA_COEF(keyp));
1243 
1244 cleanup_asn2rsapri:
1245 
1246 	if (tmp_nopad.big_value != NULL) {
1247 		(void) memset(tmp_nopad.big_value, 0x0,
1248 		    tmp_nopad.big_value_len);
1249 		free(tmp_nopad.big_value);
1250 	}
1251 
1252 	if (p8obj_asn != NULLBER)
1253 		ber_free(p8obj_asn, 1);
1254 
1255 	if (key_octs.bv_val != NULL)
1256 		free(key_octs.bv_val);
1257 
1258 	if (key_asn != NULLBER)
1259 		ber_free(key_asn, 1);
1260 
1261 	return (rv);
1262 }
1263 
1264 /* Decode ASN.1 BER syntax into DSA private key. */
1265 static CK_RV
1266 asn1_to_dsa_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
1267 {
1268 	CK_RV		rv = CKR_OK;
1269 	BerValue	p8obj_octs, key_octs;
1270 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
1271 	ber_len_t	size, tmplen;
1272 	char		*cookie;
1273 	int		version;
1274 	uchar_t		oid[sizeof (DSA_OID) + 1];
1275 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
1276 
1277 	p8obj_octs.bv_val = (char *)buf;
1278 #ifdef _LP64
1279 	/* LINTED E_CAST_INT_TO_SMALL_INT */
1280 	p8obj_octs.bv_len = (ber_len_t)buf_len;
1281 #else
1282 	p8obj_octs.bv_len = (ber_len_t)buf_len;
1283 #endif
1284 
1285 	key_octs.bv_val = NULL;
1286 	key_octs.bv_len = 0;
1287 
1288 	/* Decode PKCS#8 object ASN.1, verifying it is DSA private key. */
1289 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
1290 		return (CKR_GENERAL_ERROR);
1291 
1292 	/* PKCS#8 PrivateKeyInfo ... */
1293 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
1294 		rv = CKR_WRAPPED_KEY_INVALID;
1295 		goto cleanup_asn2dsapri;
1296 	}
1297 	/* ... begin-sequence { version, */
1298 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
1299 
1300 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1301 		rv = CKR_WRAPPED_KEY_INVALID;
1302 		goto cleanup_asn2dsapri;
1303 	}
1304 	/* ... begin-sequence { */
1305 	(void) ber_scanf(p8obj_asn, "{");
1306 
1307 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
1308 		rv = CKR_WRAPPED_KEY_INVALID;
1309 		goto cleanup_asn2dsapri;
1310 	}
1311 	/* ... OID, \* DSA algorithm OID *\ */
1312 	if (size != sizeof (DSA_OID)) {
1313 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1314 		goto cleanup_asn2dsapri;
1315 	}
1316 	size = sizeof (oid);
1317 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
1318 	if (memcmp(oid, DSA_OID, size) != 0) {
1319 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1320 		goto cleanup_asn2dsapri;
1321 	}
1322 
1323 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1324 		rv = CKR_WRAPPED_KEY_INVALID;
1325 		goto cleanup_asn2dsapri;
1326 	}
1327 	/* ... begin-sequence { */
1328 	(void) ber_scanf(p8obj_asn, "{");
1329 
1330 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1331 		rv = CKR_WRAPPED_KEY_INVALID;
1332 		goto cleanup_asn2dsapri;
1333 	}
1334 	/* ... prime, */
1335 	if (size > MAX_DSA_KEY) {
1336 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1337 		goto cleanup_asn2dsapri;
1338 	}
1339 	tmplen = size + 1;
1340 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1341 		rv = CKR_HOST_MEMORY;
1342 		goto cleanup_asn2dsapri;
1343 	}
1344 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1345 	tmp.big_value_len = tmplen;
1346 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1347 		free(tmp.big_value);
1348 		goto cleanup_asn2dsapri;
1349 	}
1350 	free(tmp.big_value);
1351 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_PRIME(keyp));
1352 
1353 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1354 		rv = CKR_WRAPPED_KEY_INVALID;
1355 		goto error_asn2dsapri;
1356 	}
1357 	/* ... subprime, */
1358 	if (size > MAX_DSA_KEY) {
1359 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1360 		goto error_asn2dsapri;
1361 	}
1362 	tmplen = size + 1;
1363 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1364 		rv = CKR_HOST_MEMORY;
1365 		goto error_asn2dsapri;
1366 	}
1367 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1368 	tmp.big_value_len = tmplen;
1369 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1370 		free(tmp.big_value);
1371 		goto error_asn2dsapri;
1372 	}
1373 	free(tmp.big_value);
1374 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_SUBPRIME(keyp));
1375 
1376 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1377 		rv = CKR_WRAPPED_KEY_INVALID;
1378 		goto error_asn2dsapri;
1379 	}
1380 	/* ... base } end-sequence } end-sequence */
1381 	if (size > MAX_DSA_KEY) {
1382 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1383 		goto error_asn2dsapri;
1384 	}
1385 	tmplen = size + 1;
1386 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1387 		rv = CKR_HOST_MEMORY;
1388 		goto error_asn2dsapri;
1389 	}
1390 	(void) ber_scanf(p8obj_asn, "s",		/* "s}}" ? */
1391 	    tmp.big_value, &tmplen);
1392 	tmp.big_value_len = tmplen;
1393 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1394 		free(tmp.big_value);
1395 		goto error_asn2dsapri;
1396 	}
1397 	free(tmp.big_value);
1398 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_BASE(keyp));
1399 
1400 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1401 		rv = CKR_WRAPPED_KEY_INVALID;
1402 		goto error_asn2dsapri;
1403 	}
1404 	/* ... DSAPrivateKey } end-sequence */
1405 	key_octs.bv_len = size + 1;
1406 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1407 		rv = CKR_HOST_MEMORY;
1408 		goto error_asn2dsapri;
1409 	}
1410 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
1411 	    key_octs.bv_val, &key_octs.bv_len);
1412 
1413 	/* Decode key octet string into softtoken key object. */
1414 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1415 		rv = CKR_GENERAL_ERROR;
1416 		goto error_asn2dsapri;
1417 	}
1418 
1419 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1420 		rv = CKR_WRAPPED_KEY_INVALID;
1421 		goto error_asn2dsapri;
1422 	}
1423 	/* ... value } end-sequence */
1424 	if (size > MAX_DSA_KEY) {
1425 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1426 		goto error_asn2dsapri;
1427 	}
1428 	tmplen = size + 1;
1429 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1430 		rv = CKR_HOST_MEMORY;
1431 		goto error_asn2dsapri;
1432 	}
1433 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
1434 	    tmp.big_value, &tmplen);
1435 	tmp.big_value_len = tmplen;
1436 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1437 		free(tmp.big_value);
1438 		goto error_asn2dsapri;
1439 	}
1440 	free(tmp.big_value);
1441 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_VALUE(keyp));
1442 
1443 	goto cleanup_asn2dsapri;
1444 
1445 error_asn2dsapri:
1446 
1447 	bigint_attr_cleanup(KEY_PRI_DSA_PRIME(keyp));
1448 	bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(keyp));
1449 	bigint_attr_cleanup(KEY_PRI_DSA_BASE(keyp));
1450 	bigint_attr_cleanup(KEY_PRI_DSA_VALUE(keyp));
1451 
1452 cleanup_asn2dsapri:
1453 
1454 	if (tmp_nopad.big_value != NULL) {
1455 		(void) memset(tmp_nopad.big_value, 0x0,
1456 		    tmp_nopad.big_value_len);
1457 		free(tmp_nopad.big_value);
1458 	}
1459 
1460 	if (p8obj_asn != NULLBER)
1461 		ber_free(p8obj_asn, 1);
1462 
1463 	if (key_octs.bv_val != NULL)
1464 		free(key_octs.bv_val);
1465 
1466 	if (key_asn != NULLBER)
1467 		ber_free(key_asn, 1);
1468 
1469 	return (rv);
1470 }
1471 
1472 /* Decode ASN.1 BER syntax into DH private key. */
1473 static CK_RV
1474 asn1_to_dh_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
1475 {
1476 	CK_RV		rv = CKR_OK;
1477 	BerValue	p8obj_octs, key_octs;
1478 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
1479 	ber_len_t	size, tmplen;
1480 	char		*cookie;
1481 	int		version;
1482 	uchar_t		oid[sizeof (DH_OID) + 1];
1483 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
1484 
1485 	p8obj_octs.bv_val = (char *)buf;
1486 #ifdef _LP64
1487 	/* LINTED E_CAST_INT_TO_SMALL_INT */
1488 	p8obj_octs.bv_len = (ber_len_t)buf_len;
1489 #else
1490 	p8obj_octs.bv_len = (ber_len_t)buf_len;
1491 #endif
1492 
1493 	key_octs.bv_val = NULL;
1494 	key_octs.bv_len = 0;
1495 
1496 	/* Decode PKCS#8 object ASN.1, verifying it is DH private key. */
1497 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
1498 		return (CKR_GENERAL_ERROR);
1499 
1500 	/* PKCS#8 PrivateKeyInfo ... */
1501 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
1502 		rv = CKR_WRAPPED_KEY_INVALID;
1503 		goto cleanup_asn2dhpri;
1504 	}
1505 	/* ... begin-sequence { version, */
1506 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
1507 
1508 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1509 		rv = CKR_WRAPPED_KEY_INVALID;
1510 		goto cleanup_asn2dhpri;
1511 	}
1512 	/* ... begin-sequence { */
1513 	(void) ber_scanf(p8obj_asn, "{");
1514 
1515 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
1516 		rv = CKR_WRAPPED_KEY_INVALID;
1517 		goto cleanup_asn2dhpri;
1518 	}
1519 	/* ... OID, \* DH algorithm OID *\ */
1520 	if (size != sizeof (DH_OID)) {
1521 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1522 		goto cleanup_asn2dhpri;
1523 	}
1524 	size = sizeof (oid);
1525 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
1526 	if (memcmp(oid, DH_OID, size) != 0) {
1527 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1528 		goto cleanup_asn2dhpri;
1529 	}
1530 
1531 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1532 		rv = CKR_WRAPPED_KEY_INVALID;
1533 		goto cleanup_asn2dhpri;
1534 	}
1535 	/* ... begin-sequence { */
1536 	(void) ber_scanf(p8obj_asn, "{");
1537 
1538 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1539 		rv = CKR_WRAPPED_KEY_INVALID;
1540 		goto cleanup_asn2dhpri;
1541 	}
1542 	/* ... prime, */
1543 	if (size > MAX_DH_KEY) {
1544 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1545 		goto cleanup_asn2dhpri;
1546 	}
1547 	tmplen = size + 1;
1548 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1549 		rv = CKR_HOST_MEMORY;
1550 		goto cleanup_asn2dhpri;
1551 	}
1552 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1553 	tmp.big_value_len = tmplen;
1554 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1555 		free(tmp.big_value);
1556 		goto cleanup_asn2dhpri;
1557 	}
1558 	free(tmp.big_value);
1559 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_PRIME(keyp));
1560 
1561 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1562 		rv = CKR_WRAPPED_KEY_INVALID;
1563 		goto error_asn2dhpri;
1564 	}
1565 	/* ... base } end-sequence } end-sequence */
1566 	if (size > MAX_DH_KEY) {
1567 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1568 		goto error_asn2dhpri;
1569 	}
1570 	tmplen = size + 1;
1571 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1572 		rv = CKR_HOST_MEMORY;
1573 		goto error_asn2dhpri;
1574 	}
1575 	(void) ber_scanf(p8obj_asn, "s",		/* "s}}" ? */
1576 	    tmp.big_value, &tmplen);
1577 	tmp.big_value_len = tmplen;
1578 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1579 		free(tmp.big_value);
1580 		goto error_asn2dhpri;
1581 	}
1582 	free(tmp.big_value);
1583 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_BASE(keyp));
1584 
1585 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1586 		rv = CKR_WRAPPED_KEY_INVALID;
1587 		goto error_asn2dhpri;
1588 	}
1589 	/* ... DHPrivateKey } end-sequence */
1590 	key_octs.bv_len = size + 1;
1591 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1592 		rv = CKR_HOST_MEMORY;
1593 		goto error_asn2dhpri;
1594 	}
1595 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
1596 	    key_octs.bv_val, &key_octs.bv_len);
1597 
1598 	/* Decode key octet string into softtoken key object. */
1599 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1600 		rv = CKR_GENERAL_ERROR;
1601 		goto error_asn2dhpri;
1602 	}
1603 
1604 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1605 		rv = CKR_WRAPPED_KEY_INVALID;
1606 		goto error_asn2dhpri;
1607 	}
1608 	/* ... value } end-sequence */
1609 	if (size > MAX_DH_KEY) {
1610 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1611 		goto error_asn2dhpri;
1612 	}
1613 	tmplen = size + 1;
1614 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1615 		rv = CKR_HOST_MEMORY;
1616 		goto error_asn2dhpri;
1617 	}
1618 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
1619 	    tmp.big_value, &tmplen);
1620 	tmp.big_value_len = tmplen;
1621 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1622 		free(tmp.big_value);
1623 		goto error_asn2dhpri;
1624 	}
1625 	free(tmp.big_value);
1626 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_VALUE(keyp));
1627 
1628 	goto cleanup_asn2dhpri;
1629 
1630 error_asn2dhpri:
1631 
1632 	bigint_attr_cleanup(KEY_PRI_DH_PRIME(keyp));
1633 	bigint_attr_cleanup(KEY_PRI_DH_BASE(keyp));
1634 	bigint_attr_cleanup(KEY_PRI_DH_VALUE(keyp));
1635 
1636 cleanup_asn2dhpri:
1637 
1638 	if (tmp_nopad.big_value != NULL) {
1639 		(void) memset(tmp_nopad.big_value, 0x0,
1640 		    tmp_nopad.big_value_len);
1641 		free(tmp_nopad.big_value);
1642 	}
1643 
1644 	if (p8obj_asn != NULLBER)
1645 		ber_free(p8obj_asn, 1);
1646 
1647 	if (key_octs.bv_val != NULL)
1648 		free(key_octs.bv_val);
1649 
1650 	if (key_asn != NULLBER)
1651 		ber_free(key_asn, 1);
1652 
1653 	return (rv);
1654 }
1655 
1656 /* Decode ASN.1 BER syntax into DH X9.42 private key. */
1657 static CK_RV
1658 asn1_to_x942_dh_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
1659 {
1660 	CK_RV		rv = CKR_OK;
1661 	BerValue	p8obj_octs, key_octs;
1662 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
1663 	ber_len_t	size, tmplen;
1664 	char		*cookie;
1665 	int		version;
1666 	uchar_t		oid[sizeof (DH942_OID) + 1];
1667 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
1668 
1669 	p8obj_octs.bv_val = (char *)buf;
1670 #ifdef _LP64
1671 	/* LINTED E_CAST_INT_TO_SMALL_INT */
1672 	p8obj_octs.bv_len = (ber_len_t)buf_len;
1673 #else
1674 	p8obj_octs.bv_len = (ber_len_t)buf_len;
1675 #endif
1676 
1677 	key_octs.bv_val = NULL;
1678 	key_octs.bv_len = 0;
1679 
1680 	/* Decode PKCS#8 object ASN.1, verifying it is DH X9.42 private key. */
1681 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
1682 		return (CKR_GENERAL_ERROR);
1683 
1684 	/* PKCS#8 PrivateKeyInfo ... */
1685 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
1686 		rv = CKR_WRAPPED_KEY_INVALID;
1687 		goto cleanup_asn2x942dhpri;
1688 	}
1689 	/* ... begin-sequence { version, */
1690 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
1691 
1692 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1693 		rv = CKR_WRAPPED_KEY_INVALID;
1694 		goto cleanup_asn2x942dhpri;
1695 	}
1696 	/* ... begin-sequence { */
1697 	(void) ber_scanf(p8obj_asn, "{");
1698 
1699 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
1700 		rv = CKR_WRAPPED_KEY_INVALID;
1701 		goto cleanup_asn2x942dhpri;
1702 	}
1703 	/* ... OID, \* DH X9.42 algorithm OID *\ */
1704 	if (size != sizeof (DH942_OID)) {
1705 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1706 		goto cleanup_asn2x942dhpri;
1707 	}
1708 	size = sizeof (oid);
1709 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
1710 	if (memcmp(oid, DH942_OID, size) != 0) {
1711 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1712 		goto cleanup_asn2x942dhpri;
1713 	}
1714 
1715 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
1716 		rv = CKR_WRAPPED_KEY_INVALID;
1717 		goto cleanup_asn2x942dhpri;
1718 	}
1719 	/* ... begin-sequence { */
1720 	(void) ber_scanf(p8obj_asn, "{");
1721 
1722 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1723 		rv = CKR_WRAPPED_KEY_INVALID;
1724 		goto cleanup_asn2x942dhpri;
1725 	}
1726 	/* ... prime, */
1727 	if (size > MAX_DH942_KEY) {
1728 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1729 		goto cleanup_asn2x942dhpri;
1730 	}
1731 	tmplen = size + 1;
1732 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1733 		rv = CKR_HOST_MEMORY;
1734 		goto cleanup_asn2x942dhpri;
1735 	}
1736 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1737 	tmp.big_value_len = tmplen;
1738 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1739 		free(tmp.big_value);
1740 		goto cleanup_asn2x942dhpri;
1741 	}
1742 	free(tmp.big_value);
1743 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_PRIME(keyp));
1744 
1745 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1746 		rv = CKR_WRAPPED_KEY_INVALID;
1747 		goto error_asn2x942dhpri;
1748 	}
1749 	/* ... base, */
1750 	if (size > MAX_DH942_KEY) {
1751 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1752 		goto error_asn2x942dhpri;
1753 	}
1754 	tmplen = size + 1;
1755 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1756 		rv = CKR_HOST_MEMORY;
1757 		goto error_asn2x942dhpri;
1758 	}
1759 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
1760 	tmp.big_value_len = tmplen;
1761 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1762 		free(tmp.big_value);
1763 		goto error_asn2x942dhpri;
1764 	}
1765 	free(tmp.big_value);
1766 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_BASE(keyp));
1767 
1768 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
1769 		rv = CKR_WRAPPED_KEY_INVALID;
1770 		goto error_asn2x942dhpri;
1771 	}
1772 	/* ... subprime } end-sequence } end-sequence */
1773 	if (size > MAX_DH942_KEY) {
1774 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1775 		goto error_asn2x942dhpri;
1776 	}
1777 	tmplen = size + 1;
1778 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1779 		rv = CKR_HOST_MEMORY;
1780 		goto error_asn2x942dhpri;
1781 	}
1782 	(void) ber_scanf(p8obj_asn, "s",		/* "s}}" ? */
1783 	    tmp.big_value, &tmplen);
1784 	tmp.big_value_len = tmplen;
1785 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1786 		free(tmp.big_value);
1787 		goto error_asn2x942dhpri;
1788 	}
1789 	free(tmp.big_value);
1790 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_SUBPRIME(keyp));
1791 
1792 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
1793 		rv = CKR_WRAPPED_KEY_INVALID;
1794 		goto error_asn2x942dhpri;
1795 	}
1796 	/* ... DHPrivateKey } end-sequence */
1797 	key_octs.bv_len = size + 1;
1798 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
1799 		rv = CKR_HOST_MEMORY;
1800 		goto error_asn2x942dhpri;
1801 	}
1802 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
1803 	    key_octs.bv_val, &key_octs.bv_len);
1804 
1805 	/* Decode key octet string into softtoken key object. */
1806 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
1807 		rv = CKR_GENERAL_ERROR;
1808 		goto error_asn2x942dhpri;
1809 	}
1810 
1811 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
1812 		rv = CKR_WRAPPED_KEY_INVALID;
1813 		goto error_asn2x942dhpri;
1814 	}
1815 	/* ... value } end-sequence */
1816 	if (size > MAX_DH942_KEY) {
1817 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1818 		goto error_asn2x942dhpri;
1819 	}
1820 	tmplen = size + 1;
1821 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
1822 		rv = CKR_HOST_MEMORY;
1823 		goto error_asn2x942dhpri;
1824 	}
1825 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
1826 	    tmp.big_value, &tmplen);
1827 	tmp.big_value_len = tmplen;
1828 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
1829 		free(tmp.big_value);
1830 		goto error_asn2x942dhpri;
1831 	}
1832 	free(tmp.big_value);
1833 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_VALUE(keyp));
1834 
1835 	goto cleanup_asn2x942dhpri;
1836 
1837 error_asn2x942dhpri:
1838 
1839 	bigint_attr_cleanup(KEY_PRI_DH942_PRIME(keyp));
1840 	bigint_attr_cleanup(KEY_PRI_DH942_BASE(keyp));
1841 	bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(keyp));
1842 	bigint_attr_cleanup(KEY_PRI_DH942_VALUE(keyp));
1843 
1844 cleanup_asn2x942dhpri:
1845 
1846 	if (tmp_nopad.big_value != NULL) {
1847 		(void) memset(tmp_nopad.big_value, 0x0,
1848 		    tmp_nopad.big_value_len);
1849 		free(tmp_nopad.big_value);
1850 	}
1851 
1852 	if (p8obj_asn != NULLBER)
1853 		ber_free(p8obj_asn, 1);
1854 
1855 	if (key_octs.bv_val != NULL)
1856 		free(key_octs.bv_val);
1857 
1858 	if (key_asn != NULLBER)
1859 		ber_free(key_asn, 1);
1860 
1861 	return (rv);
1862 }
1863 
1864 /*
1865  * Decode the object key from ASN.1 format into soft_object_t.
1866  */
1867 CK_RV
1868 soft_asn1_to_object(soft_object_t *objp, uchar_t *buf, ulong_t buf_len)
1869 {
1870 	CK_RV 		rv = CKR_OK;
1871 	CK_OBJECT_CLASS class = objp->class;
1872 	CK_KEY_TYPE	keytype = objp->key_type;
1873 	private_key_obj_t *pvk;
1874 
1875 	switch (class) {
1876 
1877 	case CKO_PRIVATE_KEY:
1878 		/* Allocate storage for Private Key Object. */
1879 		if ((pvk = calloc(1, sizeof (private_key_obj_t))) == NULL) {
1880 			rv = CKR_HOST_MEMORY;
1881 			return (rv);
1882 		}
1883 
1884 		switch (keytype) {
1885 		case CKK_RSA:
1886 			rv = asn1_to_rsa_pri(pvk, buf, buf_len);
1887 			break;
1888 
1889 		case CKK_DSA:
1890 			rv = asn1_to_dsa_pri(pvk, buf, buf_len);
1891 			break;
1892 
1893 		case CKK_DH:
1894 			rv = asn1_to_dh_pri(pvk, buf, buf_len);
1895 			break;
1896 
1897 		case CKK_X9_42_DH:
1898 			rv = asn1_to_x942_dh_pri(pvk, buf, buf_len);
1899 			break;
1900 
1901 		default:
1902 			rv = CKR_FUNCTION_NOT_SUPPORTED;
1903 			break;
1904 
1905 		} /* keytype */
1906 
1907 		if (rv != CKR_OK)
1908 			free(pvk);
1909 		else
1910 			objp->object_class_u.private_key = pvk;
1911 		break;
1912 
1913 	default:
1914 		rv = CKR_FUNCTION_NOT_SUPPORTED;
1915 		break;
1916 
1917 	} /* class */
1918 
1919 	return (rv);
1920 }
1921