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