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