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