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