xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_softtoken/common/softASN1.c (revision 33f5ff17089e3a43e6e730bf80384c233123dbd9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5034448feSmcpowers  * Common Development and Distribution License (the "License").
6034448feSmcpowers  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
22726fad2aSDina K Nimeh /*
23726fad2aSDina K Nimeh  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24*33f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
25726fad2aSDina K Nimeh  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <lber.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
327c478bd9Sstevel@tonic-gate #include "softDSA.h"
337c478bd9Sstevel@tonic-gate #include "softDH.h"
34726fad2aSDina K Nimeh #include "softRSA.h"
357c478bd9Sstevel@tonic-gate #include "softObject.h"
367c478bd9Sstevel@tonic-gate #include "softASN1.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #define	OID_TAG			0x06
397c478bd9Sstevel@tonic-gate 
40726fad2aSDina K Nimeh #define	MAX_DH_KEY	MAX_DH_KEYLENGTH_IN_BYTES	/* bytes in DH key */
417c478bd9Sstevel@tonic-gate static uchar_t	DH_OID[] = {
427c478bd9Sstevel@tonic-gate 	/* DH key agreement OID:  1 . 2 . 840 . 113549 . 1 . 3 . 1 */
437c478bd9Sstevel@tonic-gate 	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x03, 0x01
447c478bd9Sstevel@tonic-gate };
457c478bd9Sstevel@tonic-gate 
46726fad2aSDina K Nimeh #define	MAX_DH942_KEY	MAX_DH_KEYLENGTH_IN_BYTES /* bytes in DH X9.42 key */
477c478bd9Sstevel@tonic-gate static uchar_t	DH942_OID[] = {
487c478bd9Sstevel@tonic-gate 	/* DH X9.42 OID:  1 . 2 . 840 . 10046 . 1  */
497c478bd9Sstevel@tonic-gate 	0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x01
507c478bd9Sstevel@tonic-gate };
517c478bd9Sstevel@tonic-gate 
52726fad2aSDina K Nimeh #define	MAX_DSA_KEY	MAX_DSA_KEY_LEN 	/* bytes in DSA key */
537c478bd9Sstevel@tonic-gate static uchar_t	DSA_OID[] = {
547c478bd9Sstevel@tonic-gate 	/* DSA algorithm OID:  1 . 2 . 840 . 10040 . 4 . 1  */
557c478bd9Sstevel@tonic-gate 	0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #define	MAX_RSA_KEY	MAX_RSA_KEYLENGTH_IN_BYTES	/* bytes in RSA key */
597c478bd9Sstevel@tonic-gate static uchar_t	RSA_OID[] = {
607c478bd9Sstevel@tonic-gate 	/* RSA algorithm OID:  1 . 2 . 840 . 113549 . 1 . 1 . 1 */
617c478bd9Sstevel@tonic-gate 	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01
627c478bd9Sstevel@tonic-gate };
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * If the first bit of big integer is non-zero (i.e, first byte is
677c478bd9Sstevel@tonic-gate  * 0x80 or greater), it may be interpreted as an ASN.1 negative number.
687c478bd9Sstevel@tonic-gate  * Add one leading byte of zero-padding only in these cases to ensure
697c478bd9Sstevel@tonic-gate  * it is treated as an unsigned integer.
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate static CK_RV
pad_bigint_attr(biginteger_t * src,biginteger_t * dst)727c478bd9Sstevel@tonic-gate pad_bigint_attr(biginteger_t *src, biginteger_t *dst)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	int	padding;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	/* Src and dst must already by previously allocated. */
777c478bd9Sstevel@tonic-gate 	if (src == NULL || dst == NULL)
787c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
797c478bd9Sstevel@tonic-gate 
80034448feSmcpowers 	if (src->big_value_len == 0) {
81034448feSmcpowers 		dst->big_value = NULL;
82034448feSmcpowers 		dst->big_value_len = 0;
83034448feSmcpowers 		return (CKR_OK);
84034448feSmcpowers 	}
857c478bd9Sstevel@tonic-gate 	/*
867c478bd9Sstevel@tonic-gate 	 * Realloc() may free() or shrink previous memory location, so
877c478bd9Sstevel@tonic-gate 	 * clear out potentially sensitive data before that happens.
887c478bd9Sstevel@tonic-gate 	 */
897c478bd9Sstevel@tonic-gate 	if (dst->big_value != NULL)
907c478bd9Sstevel@tonic-gate 		(void) memset(dst->big_value, 0x0, dst->big_value_len);
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	padding = (src->big_value[0] < 0x80) ? 0 : 1;
937c478bd9Sstevel@tonic-gate 	dst->big_value_len = src->big_value_len + padding;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	dst->big_value = realloc(dst->big_value, dst->big_value_len);
967c478bd9Sstevel@tonic-gate 	if (dst->big_value == NULL)
977c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	/* Set zero-pad at first byte, then append actual big_value. */
1007c478bd9Sstevel@tonic-gate 	dst->big_value[0] = 0x0;
1017c478bd9Sstevel@tonic-gate 	(void) memcpy(&(dst->big_value[padding]), src->big_value,
1027c478bd9Sstevel@tonic-gate 	    src->big_value_len);
1037c478bd9Sstevel@tonic-gate 	return (CKR_OK);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate  * Sometimes there is one bytes of zero-padding, if a big integer may
1087c478bd9Sstevel@tonic-gate  * be interpreted as an ASN.1 negative number (i.e, the first bit is
1097c478bd9Sstevel@tonic-gate  * non-zero, the first byte is 0x80 or greater).  Remove first byte
1107c478bd9Sstevel@tonic-gate  * of zero-padding in those cases from the decoded octet strings.
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate static CK_RV
unpad_bigint_attr(biginteger_t src,biginteger_t * dst)1137c478bd9Sstevel@tonic-gate unpad_bigint_attr(biginteger_t src, biginteger_t *dst)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	int	offset;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	if (dst == NULL)
1187c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1197c478bd9Sstevel@tonic-gate 
120034448feSmcpowers 	if (src.big_value_len == 0) {
121034448feSmcpowers 		dst->big_value = NULL;
122034448feSmcpowers 		dst->big_value_len = 0;
123034448feSmcpowers 		return (CKR_OK);
124034448feSmcpowers 	}
125034448feSmcpowers 
1267c478bd9Sstevel@tonic-gate 	offset = (src.big_value[0] == 0x00) ? 1 : 0;
1277c478bd9Sstevel@tonic-gate 	dst->big_value_len = src.big_value_len - offset;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	/*
1307c478bd9Sstevel@tonic-gate 	 * Must allocate memory here because subsequent calls to
1317c478bd9Sstevel@tonic-gate 	 * copy_bigint_attr() just redirect pointer; it doesn't
1327c478bd9Sstevel@tonic-gate 	 * really copy the bigint like the function name implies.
1337c478bd9Sstevel@tonic-gate 	 */
1347c478bd9Sstevel@tonic-gate 	dst->big_value = malloc(dst->big_value_len);
1357c478bd9Sstevel@tonic-gate 	if (dst->big_value == NULL)
1367c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	(void) memcpy(dst->big_value, &(src.big_value[offset]),
1397c478bd9Sstevel@tonic-gate 	    dst->big_value_len);
1407c478bd9Sstevel@tonic-gate 	return (CKR_OK);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /* Encode RSA private key in ASN.1 BER syntax. */
1457c478bd9Sstevel@tonic-gate static CK_RV
rsa_pri_to_asn1(soft_object_t * objp,uchar_t * buf,ulong_t * buf_len)1467c478bd9Sstevel@tonic-gate rsa_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
1497c478bd9Sstevel@tonic-gate 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
1507c478bd9Sstevel@tonic-gate 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
1517c478bd9Sstevel@tonic-gate 	int		version = SOFT_ASN_VERSION;
1527c478bd9Sstevel@tonic-gate 	biginteger_t	tmp_pad = { NULL, 0 };
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/*
1557c478bd9Sstevel@tonic-gate 	 * The ASN.1 syntax for an RSA private key is:
1567c478bd9Sstevel@tonic-gate 	 *
1577c478bd9Sstevel@tonic-gate 	 * PKCS#8	\* PrivateKeyInfo *\
1587c478bd9Sstevel@tonic-gate 	 * ---------------------------------
1597c478bd9Sstevel@tonic-gate 	 * Sequence {
1607c478bd9Sstevel@tonic-gate 	 *	version		INTEGER;
1617c478bd9Sstevel@tonic-gate 	 *	Sequence {	\* PrivateKeyAlgorithm *\
1627c478bd9Sstevel@tonic-gate 	 *		OID	0x06,	\* RSA algorithm OID *\
1637c478bd9Sstevel@tonic-gate 	 *		param(NULL)
1647c478bd9Sstevel@tonic-gate 	 *	}
1657c478bd9Sstevel@tonic-gate 	 *	RSAPrivateKey	OCTETSTRING =
1667c478bd9Sstevel@tonic-gate 	 *		PKCS#1	\* RSAPrivateKey *\
1677c478bd9Sstevel@tonic-gate 	 *		---------------------------
1687c478bd9Sstevel@tonic-gate 	 *		Sequence {
1697c478bd9Sstevel@tonic-gate 	 *			version		INTEGER,
1707c478bd9Sstevel@tonic-gate 	 *			modulus		INTEGER,
1717c478bd9Sstevel@tonic-gate 	 *			publicExponent	INTEGER,
1727c478bd9Sstevel@tonic-gate 	 *			privateExponent	INTEGER,
1737c478bd9Sstevel@tonic-gate 	 *			prime1		INTEGER,
1747c478bd9Sstevel@tonic-gate 	 *			prime2		INTEGER,
1757c478bd9Sstevel@tonic-gate 	 *			exponent1	INTEGER,
1767c478bd9Sstevel@tonic-gate 	 *			exponent2	INTEGER,
1777c478bd9Sstevel@tonic-gate 	 *			coefficient	INTEGER
1787c478bd9Sstevel@tonic-gate 	 *		}
1797c478bd9Sstevel@tonic-gate 	 * }
1807c478bd9Sstevel@tonic-gate 	 *
1817c478bd9Sstevel@tonic-gate 	 * The code below starts building the innermost octets
1827c478bd9Sstevel@tonic-gate 	 * RSAPrivateKey, and then builds the PrivateKeyInfo
1837c478bd9Sstevel@tonic-gate 	 * sequence around that octet string.  The BER syntax
1847c478bd9Sstevel@tonic-gate 	 * used in this function is (others may be possible):
1857c478bd9Sstevel@tonic-gate 	 *	{ i { to n } { i to  to  to  to  to  to  to  to } }
1867c478bd9Sstevel@tonic-gate 	 * where "i" is for integers with fixed size
1877c478bd9Sstevel@tonic-gate 	 * where "to" is for integers that vary in size (length + value)
1887c478bd9Sstevel@tonic-gate 	 * where "n" is for nulls
1897c478bd9Sstevel@tonic-gate 	 * where "{}" delimit sequences
1907c478bd9Sstevel@tonic-gate 	 */
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	/* RSAPrivateKey ... */
1937c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_alloc()) == NULLBER)
1947c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { version, */
1977c478bd9Sstevel@tonic-gate 	if (ber_printf(key_asn, "{i", version) == -1) {
1987c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
1997c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	/* ... modulus, */
2037c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_MOD(objp), &tmp_pad)) != CKR_OK)
2047c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2057c478bd9Sstevel@tonic-gate 	if (ber_printf(key_asn, "to", LBER_INTEGER,
2067c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2077c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2087c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	/* ... public exponent, */
2127c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PUBEXPO(objp), &tmp_pad)) !=
2137c478bd9Sstevel@tonic-gate 	    CKR_OK)
2147c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
215034448feSmcpowers 
216034448feSmcpowers 	else if (ber_printf(key_asn, "to", LBER_INTEGER, tmp_pad.big_value,
217034448feSmcpowers 	    tmp_pad.big_value_len) == -1) {
2187c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2197c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	/* ... private exponent, */
2237c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIEXPO(objp), &tmp_pad)) !=
2247c478bd9Sstevel@tonic-gate 	    CKR_OK)
2257c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2267c478bd9Sstevel@tonic-gate 	if (ber_printf(key_asn, "to", LBER_INTEGER,
2277c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2287c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2297c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/* ... prime 1, */
2337c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIME1(objp), &tmp_pad)) !=
2347c478bd9Sstevel@tonic-gate 	    CKR_OK)
2357c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
236034448feSmcpowers 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
2377c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2387c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2397c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	/* ... prime 2, */
2437c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_PRIME2(objp), &tmp_pad)) !=
2447c478bd9Sstevel@tonic-gate 	    CKR_OK)
2457c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
246034448feSmcpowers 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
2477c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2487c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2497c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/* ... exponent 1, */
2537c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_EXPO1(objp), &tmp_pad)) != CKR_OK)
2547c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
255034448feSmcpowers 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
2567c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2577c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2587c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	/* ... exponent 2, */
2627c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_EXPO2(objp), &tmp_pad)) != CKR_OK)
2637c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
264034448feSmcpowers 	else if (ber_printf(key_asn, "to", LBER_INTEGER,
2657c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2667c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2677c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
270726fad2aSDina K Nimeh 	/* ... coefficient } end-sequence */
2717c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_RSA_COEF(objp), &tmp_pad)) != CKR_OK)
2727c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
273034448feSmcpowers 	else if (ber_printf(key_asn, "to}", LBER_INTEGER,
2747c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
2757c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2767c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	/* Convert key ASN.1 to octet string. */
2807c478bd9Sstevel@tonic-gate 	if (ber_flatten(key_asn, &key_octs) == -1) {
2817c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
2827c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
2867c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
2877c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
2887c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	/*
2927c478bd9Sstevel@tonic-gate 	 * Embed key octet string into PKCS#8 object ASN.1:
2937c478bd9Sstevel@tonic-gate 	 * begin-sequence {
2947c478bd9Sstevel@tonic-gate 	 *	version
2957c478bd9Sstevel@tonic-gate 	 *	begin-sequence {
2967c478bd9Sstevel@tonic-gate 	 *		OID,
2977c478bd9Sstevel@tonic-gate 	 *		NULL
2987c478bd9Sstevel@tonic-gate 	 *	} end-sequence
2997c478bd9Sstevel@tonic-gate 	 *	RSAPrivateKey
3007c478bd9Sstevel@tonic-gate 	 * } end-sequence
3017c478bd9Sstevel@tonic-gate 	 */
3027c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{i{ton}o}", version,
3037c478bd9Sstevel@tonic-gate 	    OID_TAG, RSA_OID, sizeof (RSA_OID), /* NULL parameter, */
3047c478bd9Sstevel@tonic-gate 	    key_octs->bv_val, key_octs->bv_len) == -1) {
3057c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
3067c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	/* Convert PKCS#8 object ASN.1 to octet string. */
3107c478bd9Sstevel@tonic-gate 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
3117c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
3127c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
3167c478bd9Sstevel@tonic-gate 	/*
3177c478bd9Sstevel@tonic-gate 	 * If the user passes in a null buf, then buf_len is set.
3187c478bd9Sstevel@tonic-gate 	 * If the user passes in a value with buf_len, then it can
3197c478bd9Sstevel@tonic-gate 	 * be checked to see if the accompanying buf is big enough.
3207c478bd9Sstevel@tonic-gate 	 * If it is, the octet string is copied into a pre-malloc'd
3217c478bd9Sstevel@tonic-gate 	 * buf; otherwise the user must resize buf and call again.
3227c478bd9Sstevel@tonic-gate 	 * In either case, buf_len is reset to the corrected size.
3237c478bd9Sstevel@tonic-gate 	 * See PKCS#11 section 11.2.
3247c478bd9Sstevel@tonic-gate 	 */
3257c478bd9Sstevel@tonic-gate #ifdef _LP64
3267c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
3277c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
3287c478bd9Sstevel@tonic-gate #else
3297c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
3307c478bd9Sstevel@tonic-gate #endif
3317c478bd9Sstevel@tonic-gate 		*buf_len = p8obj_octs->bv_len;
3327c478bd9Sstevel@tonic-gate 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
3337c478bd9Sstevel@tonic-gate 		goto cleanup_rsapri2asn;
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	*buf_len = p8obj_octs->bv_len;
3377c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate cleanup_rsapri2asn:
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	if (tmp_pad.big_value != NULL) {
3427c478bd9Sstevel@tonic-gate 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
3437c478bd9Sstevel@tonic-gate 		free(tmp_pad.big_value);
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
3477c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	if (key_octs != NULL)
3507c478bd9Sstevel@tonic-gate 		ber_bvfree(key_octs);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
3537c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	if (p8obj_octs != NULL)
3567c478bd9Sstevel@tonic-gate 		ber_bvfree(p8obj_octs);
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	return (rv);
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /* Encode DSA private key in ASN.1 BER syntax. */
3627c478bd9Sstevel@tonic-gate static CK_RV
3637c478bd9Sstevel@tonic-gate dsa_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
3667c478bd9Sstevel@tonic-gate 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
3677c478bd9Sstevel@tonic-gate 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
3687c478bd9Sstevel@tonic-gate 	int		version = SOFT_ASN_VERSION;
3697c478bd9Sstevel@tonic-gate 	biginteger_t	tmp_pad = { NULL, 0 };
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/*
3727c478bd9Sstevel@tonic-gate 	 * The ASN.1 syntax for a DSA private key is:
3737c478bd9Sstevel@tonic-gate 	 *
3747c478bd9Sstevel@tonic-gate 	 * PKCS#8	\* PrivateKeyInfo *\
3757c478bd9Sstevel@tonic-gate 	 * ---------------------------------
3767c478bd9Sstevel@tonic-gate 	 * Sequence {
3777c478bd9Sstevel@tonic-gate 	 *	version		INTEGER;
3787c478bd9Sstevel@tonic-gate 	 *	Sequence {	\* PrivateKeyAlgorithm *\
3797c478bd9Sstevel@tonic-gate 	 *		OID	0x06,	\* DSA algorithm OID *\
3807c478bd9Sstevel@tonic-gate 	 *		param(DSS-params)	OCTETSTRING =
3817c478bd9Sstevel@tonic-gate 	 *			PKCS#?	\* DSSParameter *\
3827c478bd9Sstevel@tonic-gate 	 *			----------------------------------
3837c478bd9Sstevel@tonic-gate 	 *			Sequence {
3847c478bd9Sstevel@tonic-gate 	 *				prime	INTEGER,
3857c478bd9Sstevel@tonic-gate 	 *				subprime INTEGER,
3867c478bd9Sstevel@tonic-gate 	 *				base	INTEGER,
3877c478bd9Sstevel@tonic-gate 	 *		}
3887c478bd9Sstevel@tonic-gate 	 *	}
3897c478bd9Sstevel@tonic-gate 	 *	DSAPrivateKey	OCTETSTRING =
3907c478bd9Sstevel@tonic-gate 	 *		PKCS#1	\* DSAPrivateKey *\
3917c478bd9Sstevel@tonic-gate 	 *		---------------------------
3927c478bd9Sstevel@tonic-gate 	 *		value		INTEGER
3937c478bd9Sstevel@tonic-gate 	 * }
3947c478bd9Sstevel@tonic-gate 	 *
3957c478bd9Sstevel@tonic-gate 	 * The code below starts building the innermost octets
3967c478bd9Sstevel@tonic-gate 	 * DSAPrivateKey, and then builds the PrivateKeyInfo
3977c478bd9Sstevel@tonic-gate 	 * sequence around that octet string.  The BER syntax
3987c478bd9Sstevel@tonic-gate 	 * used in this function is (others may be possible):
3997c478bd9Sstevel@tonic-gate 	 *	{ i { to { to to to } } to }
4007c478bd9Sstevel@tonic-gate 	 * where "i" is for integers with fixed size
4017c478bd9Sstevel@tonic-gate 	 * where "to" is for integers that vary in size (length + value)
4027c478bd9Sstevel@tonic-gate 	 * where "{}" delimit sequences
4037c478bd9Sstevel@tonic-gate 	 */
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/* DSAPrivateKey ... */
4067c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_alloc()) == NULLBER)
4077c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	/* ... value */
4107c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_VALUE(objp), &tmp_pad)) != CKR_OK)
4117c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4127c478bd9Sstevel@tonic-gate 	if (ber_printf(key_asn, "to", LBER_INTEGER,
4137c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
4147c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4157c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/* Convert key ASN.1 to octet string. */
4197c478bd9Sstevel@tonic-gate 	if (ber_flatten(key_asn, &key_octs) == -1) {
4207c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4217c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
4257c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
4267c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
4277c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	/*
4317c478bd9Sstevel@tonic-gate 	 * Start off the PKCS#8 object ASN.1:
4327c478bd9Sstevel@tonic-gate 	 * begin-sequence {
4337c478bd9Sstevel@tonic-gate 	 *	version
4347c478bd9Sstevel@tonic-gate 	 *	begin-sequence {
4357c478bd9Sstevel@tonic-gate 	 *		OID,
4367c478bd9Sstevel@tonic-gate 	 * ...
4377c478bd9Sstevel@tonic-gate 	 */
4387c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{i{to", version,
4397c478bd9Sstevel@tonic-gate 	    OID_TAG, DSA_OID, sizeof (DSA_OID)) == -1) {
4407c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4417c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	/*
4457c478bd9Sstevel@tonic-gate 	 * Add DSS parameters:
4467c478bd9Sstevel@tonic-gate 	 * ...
4477c478bd9Sstevel@tonic-gate 	 *		begin-sequence {
4487c478bd9Sstevel@tonic-gate 	 *			prime,
4497c478bd9Sstevel@tonic-gate 	 * ...
4507c478bd9Sstevel@tonic-gate 	 */
4517c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_PRIME(objp), &tmp_pad)) != CKR_OK)
4527c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4537c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
4547c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
4557c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4567c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	/*
4607c478bd9Sstevel@tonic-gate 	 * ...
4617c478bd9Sstevel@tonic-gate 	 *			subprime,
4627c478bd9Sstevel@tonic-gate 	 * ...
4637c478bd9Sstevel@tonic-gate 	 */
4647c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_SUBPRIME(objp), &tmp_pad)) !=
4657c478bd9Sstevel@tonic-gate 	    CKR_OK)
4667c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4677c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "to", LBER_INTEGER,
4687c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
4697c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4707c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	/*
4747c478bd9Sstevel@tonic-gate 	 * ...
4757c478bd9Sstevel@tonic-gate 	 *			base
4767c478bd9Sstevel@tonic-gate 	 *		} end-sequence
4777c478bd9Sstevel@tonic-gate 	 */
4787c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DSA_BASE(objp), &tmp_pad)) != CKR_OK)
4797c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4807c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
4817c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
4827c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4837c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	/*
4877c478bd9Sstevel@tonic-gate 	 * Add the key octet string:
4887c478bd9Sstevel@tonic-gate 	 *	} end-sequence
4897c478bd9Sstevel@tonic-gate 	 *	DSAPrivateKey
4907c478bd9Sstevel@tonic-gate 	 * } end-sequence
4917c478bd9Sstevel@tonic-gate 	 */
4927c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "}o}",
4937c478bd9Sstevel@tonic-gate 	    key_octs->bv_val, key_octs->bv_len) == -1) {
4947c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
4957c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	/* Convert PKCS#8 object ASN.1 to octet string. */
4997c478bd9Sstevel@tonic-gate 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
5007c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
5017c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
5057c478bd9Sstevel@tonic-gate 	/*
5067c478bd9Sstevel@tonic-gate 	 * If the user passes in a null buf, then buf_len is set.
5077c478bd9Sstevel@tonic-gate 	 * If the user passes in a value with buf_len, then it can
5087c478bd9Sstevel@tonic-gate 	 * be checked to see if the accompanying buf is big enough.
5097c478bd9Sstevel@tonic-gate 	 * If it is, the octet string is copied into a pre-malloc'd
5107c478bd9Sstevel@tonic-gate 	 * buf; otherwise the user must resize buf and call again.
5117c478bd9Sstevel@tonic-gate 	 * In either case, buf_len is reset to the corrected size.
5127c478bd9Sstevel@tonic-gate 	 * See PKCS#11 section 11.2.
5137c478bd9Sstevel@tonic-gate 	 */
5147c478bd9Sstevel@tonic-gate #ifdef _LP64
5157c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
5167c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
5177c478bd9Sstevel@tonic-gate #else
5187c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
5197c478bd9Sstevel@tonic-gate #endif
5207c478bd9Sstevel@tonic-gate 		*buf_len = p8obj_octs->bv_len;
5217c478bd9Sstevel@tonic-gate 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
5227c478bd9Sstevel@tonic-gate 		goto cleanup_dsapri2asn;
5237c478bd9Sstevel@tonic-gate 	}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	*buf_len = p8obj_octs->bv_len;
5267c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate cleanup_dsapri2asn:
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	if (tmp_pad.big_value != NULL) {
5317c478bd9Sstevel@tonic-gate 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
5327c478bd9Sstevel@tonic-gate 		free(tmp_pad.big_value);
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
5367c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	if (key_octs != NULL)
5397c478bd9Sstevel@tonic-gate 		ber_bvfree(key_octs);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
5427c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	if (p8obj_octs != NULL)
5457c478bd9Sstevel@tonic-gate 		ber_bvfree(p8obj_octs);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	return (rv);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate /* Encode DH private key in ASN.1 BER syntax. */
5517c478bd9Sstevel@tonic-gate static CK_RV
5527c478bd9Sstevel@tonic-gate dh_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
5537c478bd9Sstevel@tonic-gate {
5547c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
5557c478bd9Sstevel@tonic-gate 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
5567c478bd9Sstevel@tonic-gate 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
5577c478bd9Sstevel@tonic-gate 	int		version = SOFT_ASN_VERSION;
5587c478bd9Sstevel@tonic-gate 	biginteger_t	tmp_pad = { NULL, 0 };
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	/*
5617c478bd9Sstevel@tonic-gate 	 * The ASN.1 syntax for a DH private key is:
5627c478bd9Sstevel@tonic-gate 	 *
5637c478bd9Sstevel@tonic-gate 	 * PKCS#8	\* PrivateKeyInfo *\
5647c478bd9Sstevel@tonic-gate 	 * ---------------------------------
5657c478bd9Sstevel@tonic-gate 	 * Sequence {
5667c478bd9Sstevel@tonic-gate 	 *	version		INTEGER;
5677c478bd9Sstevel@tonic-gate 	 *	Sequence {	\* PrivateKeyAlgorithm *\
5687c478bd9Sstevel@tonic-gate 	 *		OID	0x06,	\* DH algorithm OID *\
5697c478bd9Sstevel@tonic-gate 	 *		param(DH-params) OCTETSTRING =
5707c478bd9Sstevel@tonic-gate 	 *			PKCS#3	\* DHParameter *\
5717c478bd9Sstevel@tonic-gate 	 *			-------------------------
5727c478bd9Sstevel@tonic-gate 	 *			Sequence {
5737c478bd9Sstevel@tonic-gate 	 *				prime	INTEGER,
5747c478bd9Sstevel@tonic-gate 	 *				base	INTEGER
5757c478bd9Sstevel@tonic-gate 	 *			}
5767c478bd9Sstevel@tonic-gate 	 *	}
5777c478bd9Sstevel@tonic-gate 	 *	DHPrivateKey	OCTETSTRING =
5787c478bd9Sstevel@tonic-gate 	 *		PKCS#1	\* DHPrivateKey *\
5797c478bd9Sstevel@tonic-gate 	 *		--------------------------
5807c478bd9Sstevel@tonic-gate 	 *		value		INTEGER
5817c478bd9Sstevel@tonic-gate 	 * }
5827c478bd9Sstevel@tonic-gate 	 *
5837c478bd9Sstevel@tonic-gate 	 * The code below starts building the innermost octets
5847c478bd9Sstevel@tonic-gate 	 * DHPrivateKey, and then builds the PrivateKeyInfo
5857c478bd9Sstevel@tonic-gate 	 * sequence around that octet string.  The BER syntax
5867c478bd9Sstevel@tonic-gate 	 * used in this function is (others may be possible):
5877c478bd9Sstevel@tonic-gate 	 *	{ i { to { to to } } to }
5887c478bd9Sstevel@tonic-gate 	 * where "i" is for integers with fixed size
5897c478bd9Sstevel@tonic-gate 	 * where "to" is for integers that vary in size (length + value)
5907c478bd9Sstevel@tonic-gate 	 * where "{}" delimit sequences
5917c478bd9Sstevel@tonic-gate 	 */
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/* DHPrivateKey ... */
5947c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_alloc()) == NULLBER)
5957c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	/* ... value */
5987c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH_VALUE(objp), &tmp_pad)) != CKR_OK)
5997c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6007c478bd9Sstevel@tonic-gate 	if (ber_printf(key_asn, "to", LBER_INTEGER,
6017c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
6027c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6037c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	/* Convert key ASN.1 to octet string. */
6077c478bd9Sstevel@tonic-gate 	if (ber_flatten(key_asn, &key_octs) == -1) {
6087c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6097c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
6137c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
6147c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
6157c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6167c478bd9Sstevel@tonic-gate 	}
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	/*
6197c478bd9Sstevel@tonic-gate 	 * Start off the PKCS#8 object ASN.1:
6207c478bd9Sstevel@tonic-gate 	 * begin-sequence {
6217c478bd9Sstevel@tonic-gate 	 *	version
6227c478bd9Sstevel@tonic-gate 	 *	begin-sequence {
6237c478bd9Sstevel@tonic-gate 	 *		OID,
6247c478bd9Sstevel@tonic-gate 	 * ...
6257c478bd9Sstevel@tonic-gate 	 */
6267c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{i{to", version,
6277c478bd9Sstevel@tonic-gate 	    OID_TAG, DH_OID, sizeof (DH_OID)) == -1) {
6287c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6297c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	/*
6337c478bd9Sstevel@tonic-gate 	 * Add DH parameters:
6347c478bd9Sstevel@tonic-gate 	 * ...
6357c478bd9Sstevel@tonic-gate 	 *		begin-sequence {
6367c478bd9Sstevel@tonic-gate 	 *			prime,
6377c478bd9Sstevel@tonic-gate 	 * ...
6387c478bd9Sstevel@tonic-gate 	 */
6397c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH_PRIME(objp), &tmp_pad)) != CKR_OK)
6407c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6417c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
6427c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
6437c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6447c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6457c478bd9Sstevel@tonic-gate 	}
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	/*
6487c478bd9Sstevel@tonic-gate 	 * ...
6497c478bd9Sstevel@tonic-gate 	 *			base
6507c478bd9Sstevel@tonic-gate 	 *		} end-sequence
6517c478bd9Sstevel@tonic-gate 	 */
6527c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH_BASE(objp), &tmp_pad)) != CKR_OK)
6537c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6547c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
6557c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
6567c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6577c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6587c478bd9Sstevel@tonic-gate 	}
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	/*
6617c478bd9Sstevel@tonic-gate 	 * Add the key octet string:
6627c478bd9Sstevel@tonic-gate 	 *	} end-sequence
6637c478bd9Sstevel@tonic-gate 	 *	DSAPrivateKey
6647c478bd9Sstevel@tonic-gate 	 * } end-sequence
6657c478bd9Sstevel@tonic-gate 	 */
6667c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "}o}",
6677c478bd9Sstevel@tonic-gate 	    key_octs->bv_val, key_octs->bv_len) == -1) {
6687c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6697c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	/* Convert PKCS#8 object ASN.1 to octet string. */
6737c478bd9Sstevel@tonic-gate 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
6747c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
6757c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6767c478bd9Sstevel@tonic-gate 	}
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
6797c478bd9Sstevel@tonic-gate 	/*
6807c478bd9Sstevel@tonic-gate 	 * If the user passes in a null buf, then buf_len is set.
6817c478bd9Sstevel@tonic-gate 	 * If the user passes in a value with buf_len, then it can
6827c478bd9Sstevel@tonic-gate 	 * be checked to see if the accompanying buf is big enough.
6837c478bd9Sstevel@tonic-gate 	 * If it is, the octet string is copied into a pre-malloc'd
6847c478bd9Sstevel@tonic-gate 	 * buf; otherwise the user must resize buf and call again.
6857c478bd9Sstevel@tonic-gate 	 * In either case, buf_len is reset to the corrected size.
6867c478bd9Sstevel@tonic-gate 	 * See PKCS#11 section 11.2.
6877c478bd9Sstevel@tonic-gate 	 */
6887c478bd9Sstevel@tonic-gate #ifdef _LP64
6897c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
6907c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
6917c478bd9Sstevel@tonic-gate #else
6927c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
6937c478bd9Sstevel@tonic-gate #endif
6947c478bd9Sstevel@tonic-gate 		*buf_len = p8obj_octs->bv_len;
6957c478bd9Sstevel@tonic-gate 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
6967c478bd9Sstevel@tonic-gate 		goto cleanup_dhpri2asn;
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	*buf_len = p8obj_octs->bv_len;
7007c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate cleanup_dhpri2asn:
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	if (tmp_pad.big_value != NULL) {
7057c478bd9Sstevel@tonic-gate 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
7067c478bd9Sstevel@tonic-gate 		free(tmp_pad.big_value);
7077c478bd9Sstevel@tonic-gate 	}
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
7107c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	if (key_octs != NULL)
7137c478bd9Sstevel@tonic-gate 		ber_bvfree(key_octs);
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
7167c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	if (p8obj_octs != NULL)
7197c478bd9Sstevel@tonic-gate 		ber_bvfree(p8obj_octs);
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	return (rv);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate /* Encode DH X9.42 private key in ASN.1 BER syntax. */
7257c478bd9Sstevel@tonic-gate static CK_RV
7267c478bd9Sstevel@tonic-gate x942_dh_pri_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
7277c478bd9Sstevel@tonic-gate {
7287c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
7297c478bd9Sstevel@tonic-gate 	BerElement	*key_asn = NULLBER, *p8obj_asn = NULLBER;
7307c478bd9Sstevel@tonic-gate 	BerValue	*key_octs = NULL, *p8obj_octs = NULL;
7317c478bd9Sstevel@tonic-gate 	int		version = SOFT_ASN_VERSION;
7327c478bd9Sstevel@tonic-gate 	biginteger_t	tmp_pad = { NULL, 0 };
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	/*
7357c478bd9Sstevel@tonic-gate 	 * The ASN.1 syntax for a X9.42 DH private key is:
7367c478bd9Sstevel@tonic-gate 	 *
7377c478bd9Sstevel@tonic-gate 	 * PKCS#8	\* PrivateKeyInfo *\
7387c478bd9Sstevel@tonic-gate 	 * ---------------------------------
7397c478bd9Sstevel@tonic-gate 	 * Sequence {
7407c478bd9Sstevel@tonic-gate 	 *	version		INTEGER;
7417c478bd9Sstevel@tonic-gate 	 *	Sequence {	\* PrivateKeyAlgorithm *\
7427c478bd9Sstevel@tonic-gate 	 *		OID	0x06,	\* DH X9.42 algorithm OID *\
7437c478bd9Sstevel@tonic-gate 	 *		param(DH-params) OCTETSTRING =
7447c478bd9Sstevel@tonic-gate 	 *			PKCS#3	\* DHParameter *\
7457c478bd9Sstevel@tonic-gate 	 *			-------------------------
7467c478bd9Sstevel@tonic-gate 	 *			Sequence {
7477c478bd9Sstevel@tonic-gate 	 *				prime	INTEGER,
7487c478bd9Sstevel@tonic-gate 	 *				base	INTEGER,
7497c478bd9Sstevel@tonic-gate 	 *				subprime INTEGER \* for X9.42 *\
7507c478bd9Sstevel@tonic-gate 	 *			}
7517c478bd9Sstevel@tonic-gate 	 *	}
7527c478bd9Sstevel@tonic-gate 	 *	DHPrivateKey	OCTETSTRING =
7537c478bd9Sstevel@tonic-gate 	 *		PKCS#1	\* DHPrivateKey *\
7547c478bd9Sstevel@tonic-gate 	 *		--------------------------
7557c478bd9Sstevel@tonic-gate 	 *		value		INTEGER
7567c478bd9Sstevel@tonic-gate 	 * }
7577c478bd9Sstevel@tonic-gate 	 *
7587c478bd9Sstevel@tonic-gate 	 * The code below starts building the innermost octets
7597c478bd9Sstevel@tonic-gate 	 * DHPrivateKey, and then builds the PrivateKeyInfo
7607c478bd9Sstevel@tonic-gate 	 * sequence around that octet string.  The BER syntax
7617c478bd9Sstevel@tonic-gate 	 * used in this function is (others may be possible):
7627c478bd9Sstevel@tonic-gate 	 *	{ i { to { to to } } to }
7637c478bd9Sstevel@tonic-gate 	 * where "i" is for integers with fixed size
7647c478bd9Sstevel@tonic-gate 	 * where "to" is for integers that vary in size (length + value)
7657c478bd9Sstevel@tonic-gate 	 * where "{}" delimit sequences
7667c478bd9Sstevel@tonic-gate 	 */
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	/* DHPrivateKey ... */
7697c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_alloc()) == NULLBER)
7707c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	/* ... value */
7737c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_VALUE(objp), &tmp_pad)) !=
7747c478bd9Sstevel@tonic-gate 	    CKR_OK)
7757c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
7767c478bd9Sstevel@tonic-gate 	if (ber_printf(key_asn, "to", LBER_INTEGER,
7777c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
7787c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
7797c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
7807c478bd9Sstevel@tonic-gate 	}
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	/* Convert key ASN.1 to octet string. */
7837c478bd9Sstevel@tonic-gate 	if (ber_flatten(key_asn, &key_octs) == -1) {
7847c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
7857c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
7897c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_alloc()) == NULLBER) {
7907c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
7917c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
7927c478bd9Sstevel@tonic-gate 	}
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	/*
7957c478bd9Sstevel@tonic-gate 	 * Start off the PKCS#8 object ASN.1:
7967c478bd9Sstevel@tonic-gate 	 * begin-sequence {
7977c478bd9Sstevel@tonic-gate 	 *	version
7987c478bd9Sstevel@tonic-gate 	 *	begin-sequence {
7997c478bd9Sstevel@tonic-gate 	 *		OID,
8007c478bd9Sstevel@tonic-gate 	 * ...
8017c478bd9Sstevel@tonic-gate 	 */
8027c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{i{to", version,
8037c478bd9Sstevel@tonic-gate 	    OID_TAG, DH942_OID, sizeof (DH942_OID)) == -1) {
8047c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
8057c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8067c478bd9Sstevel@tonic-gate 	}
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 	/*
8097c478bd9Sstevel@tonic-gate 	 * Add DH parameters:
8107c478bd9Sstevel@tonic-gate 	 * ...
8117c478bd9Sstevel@tonic-gate 	 *		begin-sequence {
8127c478bd9Sstevel@tonic-gate 	 *			prime,
8137c478bd9Sstevel@tonic-gate 	 * ...
8147c478bd9Sstevel@tonic-gate 	 */
8157c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_PRIME(objp), &tmp_pad)) !=
8167c478bd9Sstevel@tonic-gate 	    CKR_OK)
8177c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8187c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "{to", LBER_INTEGER,
8197c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
8207c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
8217c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	/*
8257c478bd9Sstevel@tonic-gate 	 * ...
8267c478bd9Sstevel@tonic-gate 	 *			base,
8277c478bd9Sstevel@tonic-gate 	 * ...
8287c478bd9Sstevel@tonic-gate 	 */
8297c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_BASE(objp), &tmp_pad)) !=
8307c478bd9Sstevel@tonic-gate 	    CKR_OK)
8317c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8327c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "to", LBER_INTEGER,
8337c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
8347c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
8357c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	/*
8397c478bd9Sstevel@tonic-gate 	 * ...
8407c478bd9Sstevel@tonic-gate 	 *			subprime
8417c478bd9Sstevel@tonic-gate 	 *		} end-sequence
8427c478bd9Sstevel@tonic-gate 	 */
8437c478bd9Sstevel@tonic-gate 	if ((rv = pad_bigint_attr(OBJ_PRI_DH942_SUBPRIME(objp), &tmp_pad)) !=
8447c478bd9Sstevel@tonic-gate 	    CKR_OK)
8457c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8467c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "to}", LBER_INTEGER,
8477c478bd9Sstevel@tonic-gate 	    tmp_pad.big_value, tmp_pad.big_value_len) == -1) {
8487c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
8497c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8507c478bd9Sstevel@tonic-gate 	}
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	/*
8537c478bd9Sstevel@tonic-gate 	 * Add the key octet string:
8547c478bd9Sstevel@tonic-gate 	 *	} end-sequence
8557c478bd9Sstevel@tonic-gate 	 *	DHPrivateKey
8567c478bd9Sstevel@tonic-gate 	 * } end-sequence
8577c478bd9Sstevel@tonic-gate 	 */
8587c478bd9Sstevel@tonic-gate 	if (ber_printf(p8obj_asn, "}o}",
8597c478bd9Sstevel@tonic-gate 	    key_octs->bv_val, key_octs->bv_len) == -1) {
8607c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
8617c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8627c478bd9Sstevel@tonic-gate 	}
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	/* Convert PKCS#8 object ASN.1 to octet string. */
8657c478bd9Sstevel@tonic-gate 	if (ber_flatten(p8obj_asn, &p8obj_octs) == -1) {
8667c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
8677c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8687c478bd9Sstevel@tonic-gate 	}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
8717c478bd9Sstevel@tonic-gate 	/*
8727c478bd9Sstevel@tonic-gate 	 * If the user passes in a null buf, then buf_len is set.
8737c478bd9Sstevel@tonic-gate 	 * If the user passes in a value with buf_len, then it can
8747c478bd9Sstevel@tonic-gate 	 * be checked to see if the accompanying buf is big enough.
8757c478bd9Sstevel@tonic-gate 	 * If it is, the octet string is copied into a pre-malloc'd
8767c478bd9Sstevel@tonic-gate 	 * buf; otherwise the user must resize buf and call again.
8777c478bd9Sstevel@tonic-gate 	 * In either case, buf_len is reset to the corrected size.
8787c478bd9Sstevel@tonic-gate 	 * See PKCS#11 section 11.2.
8797c478bd9Sstevel@tonic-gate 	 */
8807c478bd9Sstevel@tonic-gate #ifdef _LP64
8817c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
8827c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
8837c478bd9Sstevel@tonic-gate #else
8847c478bd9Sstevel@tonic-gate 	if ((buf == NULL) || ((ber_len_t)(*buf_len) < p8obj_octs->bv_len)) {
8857c478bd9Sstevel@tonic-gate #endif
8867c478bd9Sstevel@tonic-gate 		*buf_len = p8obj_octs->bv_len;
8877c478bd9Sstevel@tonic-gate 		rv = (buf == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL;
8887c478bd9Sstevel@tonic-gate 		goto cleanup_x942dhpri2asn;
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	*buf_len = p8obj_octs->bv_len;
8927c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, p8obj_octs->bv_val, *buf_len);
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate cleanup_x942dhpri2asn:
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	if (tmp_pad.big_value != NULL) {
8977c478bd9Sstevel@tonic-gate 		(void) memset(tmp_pad.big_value, 0x0, tmp_pad.big_value_len);
8987c478bd9Sstevel@tonic-gate 		free(tmp_pad.big_value);
8997c478bd9Sstevel@tonic-gate 	}
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
9027c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	if (key_octs != NULL)
9057c478bd9Sstevel@tonic-gate 		ber_bvfree(key_octs);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
9087c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	if (p8obj_octs != NULL)
9117c478bd9Sstevel@tonic-gate 		ber_bvfree(p8obj_octs);
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 	return (rv);
9147c478bd9Sstevel@tonic-gate }
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate /*
9177c478bd9Sstevel@tonic-gate  * Encode the object key from the soft_object_t into ASN.1 format.
9187c478bd9Sstevel@tonic-gate  */
9197c478bd9Sstevel@tonic-gate CK_RV
9207c478bd9Sstevel@tonic-gate soft_object_to_asn1(soft_object_t *objp, uchar_t *buf, ulong_t *buf_len)
9217c478bd9Sstevel@tonic-gate {
9227c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class = objp->class;
9237c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE	keytype = objp->key_type;
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	switch (class) {
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	case CKO_PRIVATE_KEY:
9287c478bd9Sstevel@tonic-gate 		switch (keytype) {
9297c478bd9Sstevel@tonic-gate 		case CKK_RSA:
9307c478bd9Sstevel@tonic-gate 			return (rsa_pri_to_asn1(objp, buf, buf_len));
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 		case CKK_DSA:
9337c478bd9Sstevel@tonic-gate 			return (dsa_pri_to_asn1(objp, buf, buf_len));
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 		case CKK_DH:
9367c478bd9Sstevel@tonic-gate 			return (dh_pri_to_asn1(objp, buf, buf_len));
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 		case CKK_X9_42_DH:
9397c478bd9Sstevel@tonic-gate 			return (x942_dh_pri_to_asn1(objp, buf, buf_len));
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 		default:
9427c478bd9Sstevel@tonic-gate 			return (CKR_FUNCTION_NOT_SUPPORTED);
9437c478bd9Sstevel@tonic-gate 		} /* keytype */
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	default:
9467c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_NOT_SUPPORTED);
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 	} /* class */
9497c478bd9Sstevel@tonic-gate }
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate /* Decode ASN.1 BER syntax into RSA private key. */
9527c478bd9Sstevel@tonic-gate static CK_RV
9537c478bd9Sstevel@tonic-gate asn1_to_rsa_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
9547c478bd9Sstevel@tonic-gate {
9557c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
9567c478bd9Sstevel@tonic-gate 	BerValue	p8obj_octs, key_octs;
9577c478bd9Sstevel@tonic-gate 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
9587c478bd9Sstevel@tonic-gate 	ber_len_t	size, tmplen;
9597c478bd9Sstevel@tonic-gate 	char		*cookie;
9607c478bd9Sstevel@tonic-gate 	int		version;
9617c478bd9Sstevel@tonic-gate 	uchar_t		oid[sizeof (RSA_OID) + 1];
9627c478bd9Sstevel@tonic-gate 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_val = (char *)buf;
9657c478bd9Sstevel@tonic-gate #ifdef _LP64
9667c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
9677c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
9687c478bd9Sstevel@tonic-gate #else
9697c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
9707c478bd9Sstevel@tonic-gate #endif
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 	key_octs.bv_val = NULL;
9737c478bd9Sstevel@tonic-gate 	key_octs.bv_len = 0;
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 	/* Decode PKCS#8 object ASN.1, verifying it is RSA private key. */
9767c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
9777c478bd9Sstevel@tonic-gate 		return (CKR_GENERAL_ERROR);
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
9807c478bd9Sstevel@tonic-gate 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
9817c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
9827c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
9837c478bd9Sstevel@tonic-gate 	}
9847c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { version, */
9857c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
9887c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
9897c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
9907c478bd9Sstevel@tonic-gate 	}
9917c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
9927c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
9957c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
9967c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
9977c478bd9Sstevel@tonic-gate 	}
9987c478bd9Sstevel@tonic-gate 	/* ... OID, \* RSA algorithm OID *\ */
9997c478bd9Sstevel@tonic-gate 	if (size != sizeof (RSA_OID)) {
10007c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
10017c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10027c478bd9Sstevel@tonic-gate 	}
10037c478bd9Sstevel@tonic-gate 	size = sizeof (oid);
10047c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
10057c478bd9Sstevel@tonic-gate 	if (memcmp(oid, RSA_OID, size) != 0) {
10067c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
10077c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10087c478bd9Sstevel@tonic-gate 	}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_NULL) {
10117c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
10127c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10137c478bd9Sstevel@tonic-gate 	}
10147c478bd9Sstevel@tonic-gate 	/* ... param(NULL) } end-sequence */
10157c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "n");		/* "n}" ? */
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
10187c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
10197c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10207c478bd9Sstevel@tonic-gate 	}
10217c478bd9Sstevel@tonic-gate 	/* ... RSAPrivateKey } end-sequence */
10227c478bd9Sstevel@tonic-gate 	key_octs.bv_len = size + 1;
10237c478bd9Sstevel@tonic-gate 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
10247c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
10257c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10267c478bd9Sstevel@tonic-gate 	}
10277c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
10287c478bd9Sstevel@tonic-gate 	    key_octs.bv_val, &key_octs.bv_len);
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	/* Decode key octet string into softtoken key object. */
10317c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
10327c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
10337c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10347c478bd9Sstevel@tonic-gate 	}
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { version, */
10377c478bd9Sstevel@tonic-gate 	if (ber_first_element(key_asn, &size, &cookie) != LBER_INTEGER) {
10387c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
10397c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10407c478bd9Sstevel@tonic-gate 	}
10417c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "i", &version);	/* "{i" ? */
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	/* ... modulus, */
10447c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
10457c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
10467c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
10497c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
10507c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10517c478bd9Sstevel@tonic-gate 	}
10527c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
10537c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
10547c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
10557c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
10567c478bd9Sstevel@tonic-gate 	}
10577c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
10587c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
105901223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
106001223cbaSmcpowers 		free(tmp.big_value);
10617c478bd9Sstevel@tonic-gate 		goto cleanup_asn2rsapri;
106201223cbaSmcpowers 	}
106301223cbaSmcpowers 	free(tmp.big_value);
10647c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_MOD(keyp));
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	/* ... public exponent, */
10677c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
10687c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
10697c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
10707c478bd9Sstevel@tonic-gate 	}
10717c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
10727c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
10737c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
10747c478bd9Sstevel@tonic-gate 	}
10757c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
10767c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
10777c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
10787c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
10797c478bd9Sstevel@tonic-gate 	}
10807c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
10817c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
108201223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
108301223cbaSmcpowers 		free(tmp.big_value);
10847c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
108501223cbaSmcpowers 	}
108601223cbaSmcpowers 	free(tmp.big_value);
10877c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PUBEXPO(keyp));
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	/* ... private exponent, */
10907c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
10917c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
10927c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
10937c478bd9Sstevel@tonic-gate 	}
10947c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
10957c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
10967c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
10977c478bd9Sstevel@tonic-gate 	}
10987c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
10997c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
11007c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
11017c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11027c478bd9Sstevel@tonic-gate 	}
11037c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
11047c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
110501223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
110601223cbaSmcpowers 		free(tmp.big_value);
11077c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
110801223cbaSmcpowers 	}
110901223cbaSmcpowers 	free(tmp.big_value);
11107c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIEXPO(keyp));
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	/* ... prime 1, */
11137c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
11147c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
11157c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11167c478bd9Sstevel@tonic-gate 	}
11177c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
11187c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
11197c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11207c478bd9Sstevel@tonic-gate 	}
11217c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
11227c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
11237c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
11247c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11257c478bd9Sstevel@tonic-gate 	}
11267c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
11277c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
112801223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
112901223cbaSmcpowers 		free(tmp.big_value);
11307c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
113101223cbaSmcpowers 	}
113201223cbaSmcpowers 	free(tmp.big_value);
11337c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIME1(keyp));
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	/* ... prime 2, */
11367c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
11377c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
11387c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11397c478bd9Sstevel@tonic-gate 	}
11407c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
11417c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
11427c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11437c478bd9Sstevel@tonic-gate 	}
11447c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
11457c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
11467c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
11477c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11487c478bd9Sstevel@tonic-gate 	}
11497c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
11507c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
115101223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
115201223cbaSmcpowers 		free(tmp.big_value);
11537c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
115401223cbaSmcpowers 	}
115501223cbaSmcpowers 	free(tmp.big_value);
11567c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_PRIME2(keyp));
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	/* ... exponent 1, */
11597c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
11607c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
11617c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11627c478bd9Sstevel@tonic-gate 	}
11637c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
11647c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
11657c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
11687c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
11697c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
11707c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11717c478bd9Sstevel@tonic-gate 	}
11727c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
11737c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
117401223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
117501223cbaSmcpowers 		free(tmp.big_value);
11767c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
117701223cbaSmcpowers 	}
117801223cbaSmcpowers 	free(tmp.big_value);
11797c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_EXPO1(keyp));
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	/* ... exponent 2, */
11827c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
11837c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
11847c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11857c478bd9Sstevel@tonic-gate 	}
11867c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
11877c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
11887c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11897c478bd9Sstevel@tonic-gate 	}
11907c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
11917c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
11927c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
11937c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
11947c478bd9Sstevel@tonic-gate 	}
11957c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s", tmp.big_value, &tmplen);
11967c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
119701223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
119801223cbaSmcpowers 		free(tmp.big_value);
11997c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
120001223cbaSmcpowers 	}
120101223cbaSmcpowers 	free(tmp.big_value);
12027c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_EXPO2(keyp));
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	/* ... coefficient } end-sequence */
12057c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
12067c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
12077c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
12087c478bd9Sstevel@tonic-gate 	}
12097c478bd9Sstevel@tonic-gate 	if (size > MAX_RSA_KEY) {
12107c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
12117c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
12127c478bd9Sstevel@tonic-gate 	}
12137c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
12147c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
12157c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
12167c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
12177c478bd9Sstevel@tonic-gate 	}
12187c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
12197c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
12207c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
122101223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
122201223cbaSmcpowers 		free(tmp.big_value);
12237c478bd9Sstevel@tonic-gate 		goto error_asn2rsapri;
122401223cbaSmcpowers 	}
122501223cbaSmcpowers 	free(tmp.big_value);
12267c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_RSA_COEF(keyp));
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate 	goto cleanup_asn2rsapri;
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate error_asn2rsapri:
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_MOD(keyp));
12337c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(keyp));
12347c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(keyp));
12357c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(keyp));
12367c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(keyp));
12377c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(keyp));
12387c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(keyp));
12397c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_RSA_COEF(keyp));
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate cleanup_asn2rsapri:
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	if (tmp_nopad.big_value != NULL) {
12447c478bd9Sstevel@tonic-gate 		(void) memset(tmp_nopad.big_value, 0x0,
12457c478bd9Sstevel@tonic-gate 		    tmp_nopad.big_value_len);
12467c478bd9Sstevel@tonic-gate 		free(tmp_nopad.big_value);
12477c478bd9Sstevel@tonic-gate 	}
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
12507c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	if (key_octs.bv_val != NULL)
12537c478bd9Sstevel@tonic-gate 		free(key_octs.bv_val);
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
12567c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	return (rv);
12597c478bd9Sstevel@tonic-gate }
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate /* Decode ASN.1 BER syntax into DSA private key. */
12627c478bd9Sstevel@tonic-gate static CK_RV
12637c478bd9Sstevel@tonic-gate asn1_to_dsa_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
12647c478bd9Sstevel@tonic-gate {
12657c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
12667c478bd9Sstevel@tonic-gate 	BerValue	p8obj_octs, key_octs;
12677c478bd9Sstevel@tonic-gate 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
12687c478bd9Sstevel@tonic-gate 	ber_len_t	size, tmplen;
12697c478bd9Sstevel@tonic-gate 	char		*cookie;
12707c478bd9Sstevel@tonic-gate 	int		version;
12717c478bd9Sstevel@tonic-gate 	uchar_t		oid[sizeof (DSA_OID) + 1];
12727c478bd9Sstevel@tonic-gate 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_val = (char *)buf;
12757c478bd9Sstevel@tonic-gate #ifdef _LP64
12767c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
12777c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
12787c478bd9Sstevel@tonic-gate #else
12797c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
12807c478bd9Sstevel@tonic-gate #endif
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	key_octs.bv_val = NULL;
12837c478bd9Sstevel@tonic-gate 	key_octs.bv_len = 0;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	/* Decode PKCS#8 object ASN.1, verifying it is DSA private key. */
12867c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
12877c478bd9Sstevel@tonic-gate 		return (CKR_GENERAL_ERROR);
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
12907c478bd9Sstevel@tonic-gate 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
12917c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
12927c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { version, */
12957c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
12987c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
12997c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13007c478bd9Sstevel@tonic-gate 	}
13017c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
13027c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
13057c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
13067c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13077c478bd9Sstevel@tonic-gate 	}
13087c478bd9Sstevel@tonic-gate 	/* ... OID, \* DSA algorithm OID *\ */
13097c478bd9Sstevel@tonic-gate 	if (size != sizeof (DSA_OID)) {
13107c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
13117c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13127c478bd9Sstevel@tonic-gate 	}
13137c478bd9Sstevel@tonic-gate 	size = sizeof (oid);
13147c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
13157c478bd9Sstevel@tonic-gate 	if (memcmp(oid, DSA_OID, size) != 0) {
13167c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
13177c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13187c478bd9Sstevel@tonic-gate 	}
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
13217c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
13227c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13237c478bd9Sstevel@tonic-gate 	}
13247c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
13257c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
13287c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
13297c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13307c478bd9Sstevel@tonic-gate 	}
13317c478bd9Sstevel@tonic-gate 	/* ... prime, */
13327c478bd9Sstevel@tonic-gate 	if (size > MAX_DSA_KEY) {
13337c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
13347c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13357c478bd9Sstevel@tonic-gate 	}
13367c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
13377c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
13387c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
13397c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
13407c478bd9Sstevel@tonic-gate 	}
13417c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
13427c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
134301223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
134401223cbaSmcpowers 		free(tmp.big_value);
13457c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dsapri;
134601223cbaSmcpowers 	}
134701223cbaSmcpowers 	free(tmp.big_value);
13487c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_PRIME(keyp));
13497c478bd9Sstevel@tonic-gate 
13507c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
13517c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
13527c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate 	/* ... subprime, */
13557c478bd9Sstevel@tonic-gate 	if (size > MAX_DSA_KEY) {
13567c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
13577c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
13587c478bd9Sstevel@tonic-gate 	}
13597c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
13607c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
13617c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
13627c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
13637c478bd9Sstevel@tonic-gate 	}
13647c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
13657c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
136601223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
136701223cbaSmcpowers 		free(tmp.big_value);
13687c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
136901223cbaSmcpowers 	}
137001223cbaSmcpowers 	free(tmp.big_value);
13717c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_SUBPRIME(keyp));
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
13747c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
13757c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
13767c478bd9Sstevel@tonic-gate 	}
13777c478bd9Sstevel@tonic-gate 	/* ... base } end-sequence } end-sequence */
13787c478bd9Sstevel@tonic-gate 	if (size > MAX_DSA_KEY) {
13797c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
13807c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
13817c478bd9Sstevel@tonic-gate 	}
13827c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
13837c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
13847c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
13857c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
13867c478bd9Sstevel@tonic-gate 	}
13877c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}}" ? */
13887c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
13897c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
139001223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
139101223cbaSmcpowers 		free(tmp.big_value);
13927c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
139301223cbaSmcpowers 	}
139401223cbaSmcpowers 	free(tmp.big_value);
13957c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_BASE(keyp));
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
13987c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
13997c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
14007c478bd9Sstevel@tonic-gate 	}
14017c478bd9Sstevel@tonic-gate 	/* ... DSAPrivateKey } end-sequence */
14027c478bd9Sstevel@tonic-gate 	key_octs.bv_len = size + 1;
14037c478bd9Sstevel@tonic-gate 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
14047c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
14057c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
14067c478bd9Sstevel@tonic-gate 	}
14077c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
14087c478bd9Sstevel@tonic-gate 	    key_octs.bv_val, &key_octs.bv_len);
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 	/* Decode key octet string into softtoken key object. */
14117c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
14127c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
14137c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
14147c478bd9Sstevel@tonic-gate 	}
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
14177c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
14187c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
14197c478bd9Sstevel@tonic-gate 	}
14207c478bd9Sstevel@tonic-gate 	/* ... value } end-sequence */
14217c478bd9Sstevel@tonic-gate 	if (size > MAX_DSA_KEY) {
14227c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
14237c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
14247c478bd9Sstevel@tonic-gate 	}
14257c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
14267c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
14277c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
14287c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
14297c478bd9Sstevel@tonic-gate 	}
14307c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
14317c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
14327c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
143301223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
143401223cbaSmcpowers 		free(tmp.big_value);
14357c478bd9Sstevel@tonic-gate 		goto error_asn2dsapri;
143601223cbaSmcpowers 	}
143701223cbaSmcpowers 	free(tmp.big_value);
14387c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DSA_VALUE(keyp));
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 	goto cleanup_asn2dsapri;
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate error_asn2dsapri:
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DSA_PRIME(keyp));
14457c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(keyp));
14467c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DSA_BASE(keyp));
14477c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DSA_VALUE(keyp));
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate cleanup_asn2dsapri:
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	if (tmp_nopad.big_value != NULL) {
14527c478bd9Sstevel@tonic-gate 		(void) memset(tmp_nopad.big_value, 0x0,
14537c478bd9Sstevel@tonic-gate 		    tmp_nopad.big_value_len);
14547c478bd9Sstevel@tonic-gate 		free(tmp_nopad.big_value);
14557c478bd9Sstevel@tonic-gate 	}
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
14587c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 	if (key_octs.bv_val != NULL)
14617c478bd9Sstevel@tonic-gate 		free(key_octs.bv_val);
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
14647c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	return (rv);
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate /* Decode ASN.1 BER syntax into DH private key. */
14707c478bd9Sstevel@tonic-gate static CK_RV
14717c478bd9Sstevel@tonic-gate asn1_to_dh_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
14727c478bd9Sstevel@tonic-gate {
14737c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
14747c478bd9Sstevel@tonic-gate 	BerValue	p8obj_octs, key_octs;
14757c478bd9Sstevel@tonic-gate 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
14767c478bd9Sstevel@tonic-gate 	ber_len_t	size, tmplen;
14777c478bd9Sstevel@tonic-gate 	char		*cookie;
14787c478bd9Sstevel@tonic-gate 	int		version;
14797c478bd9Sstevel@tonic-gate 	uchar_t		oid[sizeof (DH_OID) + 1];
14807c478bd9Sstevel@tonic-gate 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_val = (char *)buf;
14837c478bd9Sstevel@tonic-gate #ifdef _LP64
14847c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
14857c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
14867c478bd9Sstevel@tonic-gate #else
14877c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
14887c478bd9Sstevel@tonic-gate #endif
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	key_octs.bv_val = NULL;
14917c478bd9Sstevel@tonic-gate 	key_octs.bv_len = 0;
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	/* Decode PKCS#8 object ASN.1, verifying it is DH private key. */
14947c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
14957c478bd9Sstevel@tonic-gate 		return (CKR_GENERAL_ERROR);
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
14987c478bd9Sstevel@tonic-gate 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
14997c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15007c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15017c478bd9Sstevel@tonic-gate 	}
15027c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { version, */
15037c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
15067c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15077c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15087c478bd9Sstevel@tonic-gate 	}
15097c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
15107c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
15137c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15147c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15157c478bd9Sstevel@tonic-gate 	}
15167c478bd9Sstevel@tonic-gate 	/* ... OID, \* DH algorithm OID *\ */
15177c478bd9Sstevel@tonic-gate 	if (size != sizeof (DH_OID)) {
15187c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
15197c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15207c478bd9Sstevel@tonic-gate 	}
15217c478bd9Sstevel@tonic-gate 	size = sizeof (oid);
15227c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
15237c478bd9Sstevel@tonic-gate 	if (memcmp(oid, DH_OID, size) != 0) {
15247c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
15257c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15267c478bd9Sstevel@tonic-gate 	}
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
15297c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15307c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15317c478bd9Sstevel@tonic-gate 	}
15327c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
15337c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
15367c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15377c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15387c478bd9Sstevel@tonic-gate 	}
15397c478bd9Sstevel@tonic-gate 	/* ... prime, */
15407c478bd9Sstevel@tonic-gate 	if (size > MAX_DH_KEY) {
15417c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
15427c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15437c478bd9Sstevel@tonic-gate 	}
15447c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
15457c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
15467c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
15477c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
15487c478bd9Sstevel@tonic-gate 	}
15497c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
15507c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
155101223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
155201223cbaSmcpowers 		free(tmp.big_value);
15537c478bd9Sstevel@tonic-gate 		goto cleanup_asn2dhpri;
155401223cbaSmcpowers 	}
155501223cbaSmcpowers 	free(tmp.big_value);
15567c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_PRIME(keyp));
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
15597c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15607c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
15617c478bd9Sstevel@tonic-gate 	}
15627c478bd9Sstevel@tonic-gate 	/* ... base } end-sequence } end-sequence */
15637c478bd9Sstevel@tonic-gate 	if (size > MAX_DH_KEY) {
15647c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
15657c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
15667c478bd9Sstevel@tonic-gate 	}
15677c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
15687c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
15697c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
15707c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
15717c478bd9Sstevel@tonic-gate 	}
15727c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}}" ? */
15737c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
15747c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
157501223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
157601223cbaSmcpowers 		free(tmp.big_value);
15777c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
157801223cbaSmcpowers 	}
157901223cbaSmcpowers 	free(tmp.big_value);
15807c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_BASE(keyp));
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
15837c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
15847c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
15857c478bd9Sstevel@tonic-gate 	}
15867c478bd9Sstevel@tonic-gate 	/* ... DHPrivateKey } end-sequence */
15877c478bd9Sstevel@tonic-gate 	key_octs.bv_len = size + 1;
15887c478bd9Sstevel@tonic-gate 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
15897c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
15907c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
15917c478bd9Sstevel@tonic-gate 	}
15927c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
15937c478bd9Sstevel@tonic-gate 	    key_octs.bv_val, &key_octs.bv_len);
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate 	/* Decode key octet string into softtoken key object. */
15967c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
15977c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
15987c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
15997c478bd9Sstevel@tonic-gate 	}
16007c478bd9Sstevel@tonic-gate 
16017c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
16027c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
16037c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
16047c478bd9Sstevel@tonic-gate 	}
16057c478bd9Sstevel@tonic-gate 	/* ... value } end-sequence */
16067c478bd9Sstevel@tonic-gate 	if (size > MAX_DH_KEY) {
16077c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
16087c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
16097c478bd9Sstevel@tonic-gate 	}
16107c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
16117c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
16127c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
16137c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
16147c478bd9Sstevel@tonic-gate 	}
16157c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
16167c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
16177c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
161801223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
161901223cbaSmcpowers 		free(tmp.big_value);
16207c478bd9Sstevel@tonic-gate 		goto error_asn2dhpri;
162101223cbaSmcpowers 	}
162201223cbaSmcpowers 	free(tmp.big_value);
16237c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH_VALUE(keyp));
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate 	goto cleanup_asn2dhpri;
16267c478bd9Sstevel@tonic-gate 
16277c478bd9Sstevel@tonic-gate error_asn2dhpri:
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH_PRIME(keyp));
16307c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH_BASE(keyp));
16317c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH_VALUE(keyp));
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate cleanup_asn2dhpri:
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 	if (tmp_nopad.big_value != NULL) {
16367c478bd9Sstevel@tonic-gate 		(void) memset(tmp_nopad.big_value, 0x0,
16377c478bd9Sstevel@tonic-gate 		    tmp_nopad.big_value_len);
16387c478bd9Sstevel@tonic-gate 		free(tmp_nopad.big_value);
16397c478bd9Sstevel@tonic-gate 	}
16407c478bd9Sstevel@tonic-gate 
16417c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
16427c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate 	if (key_octs.bv_val != NULL)
16457c478bd9Sstevel@tonic-gate 		free(key_octs.bv_val);
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
16487c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	return (rv);
16517c478bd9Sstevel@tonic-gate }
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate /* Decode ASN.1 BER syntax into DH X9.42 private key. */
16547c478bd9Sstevel@tonic-gate static CK_RV
16557c478bd9Sstevel@tonic-gate asn1_to_x942_dh_pri(private_key_obj_t *keyp, uchar_t *buf, ulong_t buf_len)
16567c478bd9Sstevel@tonic-gate {
16577c478bd9Sstevel@tonic-gate 	CK_RV		rv = CKR_OK;
16587c478bd9Sstevel@tonic-gate 	BerValue	p8obj_octs, key_octs;
16597c478bd9Sstevel@tonic-gate 	BerElement	*p8obj_asn = NULLBER, *key_asn = NULLBER;
16607c478bd9Sstevel@tonic-gate 	ber_len_t	size, tmplen;
16617c478bd9Sstevel@tonic-gate 	char		*cookie;
16627c478bd9Sstevel@tonic-gate 	int		version;
16637c478bd9Sstevel@tonic-gate 	uchar_t		oid[sizeof (DH942_OID) + 1];
16647c478bd9Sstevel@tonic-gate 	biginteger_t	tmp, tmp_nopad = { NULL, 0 };
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_val = (char *)buf;
16677c478bd9Sstevel@tonic-gate #ifdef _LP64
16687c478bd9Sstevel@tonic-gate 	/* LINTED E_CAST_INT_TO_SMALL_INT */
16697c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
16707c478bd9Sstevel@tonic-gate #else
16717c478bd9Sstevel@tonic-gate 	p8obj_octs.bv_len = (ber_len_t)buf_len;
16727c478bd9Sstevel@tonic-gate #endif
16737c478bd9Sstevel@tonic-gate 
16747c478bd9Sstevel@tonic-gate 	key_octs.bv_val = NULL;
16757c478bd9Sstevel@tonic-gate 	key_octs.bv_len = 0;
16767c478bd9Sstevel@tonic-gate 
16777c478bd9Sstevel@tonic-gate 	/* Decode PKCS#8 object ASN.1, verifying it is DH X9.42 private key. */
16787c478bd9Sstevel@tonic-gate 	if ((p8obj_asn = ber_init(&p8obj_octs)) == NULLBER)
16797c478bd9Sstevel@tonic-gate 		return (CKR_GENERAL_ERROR);
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 	/* PKCS#8 PrivateKeyInfo ... */
16827c478bd9Sstevel@tonic-gate 	if (ber_first_element(p8obj_asn, &size, &cookie) != LBER_INTEGER) {
16837c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
16847c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
16857c478bd9Sstevel@tonic-gate 	}
16867c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { version, */
16877c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "i", &version);	/* "{i" ? */
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
16907c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
16917c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
16927c478bd9Sstevel@tonic-gate 	}
16937c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
16947c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
16957c478bd9Sstevel@tonic-gate 
16967c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != OID_TAG) {
16977c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
16987c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
16997c478bd9Sstevel@tonic-gate 	}
17007c478bd9Sstevel@tonic-gate 	/* ... OID, \* DH X9.42 algorithm OID *\ */
17017c478bd9Sstevel@tonic-gate 	if (size != sizeof (DH942_OID)) {
17027c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
17037c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
17047c478bd9Sstevel@tonic-gate 	}
17057c478bd9Sstevel@tonic-gate 	size = sizeof (oid);
17067c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", oid, &size);
17077c478bd9Sstevel@tonic-gate 	if (memcmp(oid, DH942_OID, size) != 0) {
17087c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
17097c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
17107c478bd9Sstevel@tonic-gate 	}
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_SEQUENCE) {
17137c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
17147c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
17157c478bd9Sstevel@tonic-gate 	}
17167c478bd9Sstevel@tonic-gate 	/* ... begin-sequence { */
17177c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "{");
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
17207c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
17217c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
17227c478bd9Sstevel@tonic-gate 	}
17237c478bd9Sstevel@tonic-gate 	/* ... prime, */
17247c478bd9Sstevel@tonic-gate 	if (size > MAX_DH942_KEY) {
17257c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
17267c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
17277c478bd9Sstevel@tonic-gate 	}
17287c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
17297c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
17307c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
17317c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
17327c478bd9Sstevel@tonic-gate 	}
17337c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
17347c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
173501223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
173601223cbaSmcpowers 		free(tmp.big_value);
17377c478bd9Sstevel@tonic-gate 		goto cleanup_asn2x942dhpri;
173801223cbaSmcpowers 	}
173901223cbaSmcpowers 	free(tmp.big_value);
17407c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_PRIME(keyp));
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
17437c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
17447c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17457c478bd9Sstevel@tonic-gate 	}
17467c478bd9Sstevel@tonic-gate 	/* ... base, */
17477c478bd9Sstevel@tonic-gate 	if (size > MAX_DH942_KEY) {
17487c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
17497c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17507c478bd9Sstevel@tonic-gate 	}
17517c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
17527c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
17537c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
17547c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17557c478bd9Sstevel@tonic-gate 	}
17567c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s", tmp.big_value, &tmplen);
17577c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
175801223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
175901223cbaSmcpowers 		free(tmp.big_value);
17607c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
176101223cbaSmcpowers 	}
176201223cbaSmcpowers 	free(tmp.big_value);
17637c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_BASE(keyp));
17647c478bd9Sstevel@tonic-gate 
17657c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_INTEGER) {
17667c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
17677c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17687c478bd9Sstevel@tonic-gate 	}
17697c478bd9Sstevel@tonic-gate 	/* ... subprime } end-sequence } end-sequence */
17707c478bd9Sstevel@tonic-gate 	if (size > MAX_DH942_KEY) {
17717c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
17727c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17737c478bd9Sstevel@tonic-gate 	}
17747c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
17757c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
17767c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
17777c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17787c478bd9Sstevel@tonic-gate 	}
17797c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}}" ? */
17807c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
17817c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
178201223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
178301223cbaSmcpowers 		free(tmp.big_value);
17847c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
178501223cbaSmcpowers 	}
178601223cbaSmcpowers 	free(tmp.big_value);
17877c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_SUBPRIME(keyp));
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate 	if (ber_next_element(p8obj_asn, &size, cookie) != LBER_OCTETSTRING) {
17907c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
17917c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17927c478bd9Sstevel@tonic-gate 	}
17937c478bd9Sstevel@tonic-gate 	/* ... DHPrivateKey } end-sequence */
17947c478bd9Sstevel@tonic-gate 	key_octs.bv_len = size + 1;
17957c478bd9Sstevel@tonic-gate 	if ((key_octs.bv_val = malloc(size + 1)) == NULL) {
17967c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
17977c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
17987c478bd9Sstevel@tonic-gate 	}
17997c478bd9Sstevel@tonic-gate 	(void) ber_scanf(p8obj_asn, "s",		/* "s}" ? */
18007c478bd9Sstevel@tonic-gate 	    key_octs.bv_val, &key_octs.bv_len);
18017c478bd9Sstevel@tonic-gate 
18027c478bd9Sstevel@tonic-gate 	/* Decode key octet string into softtoken key object. */
18037c478bd9Sstevel@tonic-gate 	if ((key_asn = ber_init(&key_octs)) == NULLBER) {
18047c478bd9Sstevel@tonic-gate 		rv = CKR_GENERAL_ERROR;
18057c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
18067c478bd9Sstevel@tonic-gate 	}
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 	if (ber_next_element(key_asn, &size, cookie) != LBER_INTEGER) {
18097c478bd9Sstevel@tonic-gate 		rv = CKR_WRAPPED_KEY_INVALID;
18107c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
18117c478bd9Sstevel@tonic-gate 	}
18127c478bd9Sstevel@tonic-gate 	/* ... value } end-sequence */
18137c478bd9Sstevel@tonic-gate 	if (size > MAX_DH942_KEY) {
18147c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
18157c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
18167c478bd9Sstevel@tonic-gate 	}
18177c478bd9Sstevel@tonic-gate 	tmplen = size + 1;
18187c478bd9Sstevel@tonic-gate 	if ((tmp.big_value = malloc(tmplen)) == NULL) {
18197c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
18207c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
18217c478bd9Sstevel@tonic-gate 	}
18227c478bd9Sstevel@tonic-gate 	(void) ber_scanf(key_asn, "s",		/* "s}" ? */
18237c478bd9Sstevel@tonic-gate 	    tmp.big_value, &tmplen);
18247c478bd9Sstevel@tonic-gate 	tmp.big_value_len = tmplen;
182501223cbaSmcpowers 	if ((rv = unpad_bigint_attr(tmp, &tmp_nopad)) != CKR_OK) {
182601223cbaSmcpowers 		free(tmp.big_value);
18277c478bd9Sstevel@tonic-gate 		goto error_asn2x942dhpri;
182801223cbaSmcpowers 	}
182901223cbaSmcpowers 	free(tmp.big_value);
18307c478bd9Sstevel@tonic-gate 	copy_bigint_attr(&tmp_nopad, KEY_PRI_DH942_VALUE(keyp));
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 	goto cleanup_asn2x942dhpri;
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate error_asn2x942dhpri:
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH942_PRIME(keyp));
18377c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH942_BASE(keyp));
18387c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(keyp));
18397c478bd9Sstevel@tonic-gate 	bigint_attr_cleanup(KEY_PRI_DH942_VALUE(keyp));
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate cleanup_asn2x942dhpri:
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate 	if (tmp_nopad.big_value != NULL) {
18447c478bd9Sstevel@tonic-gate 		(void) memset(tmp_nopad.big_value, 0x0,
18457c478bd9Sstevel@tonic-gate 		    tmp_nopad.big_value_len);
18467c478bd9Sstevel@tonic-gate 		free(tmp_nopad.big_value);
18477c478bd9Sstevel@tonic-gate 	}
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 	if (p8obj_asn != NULLBER)
18507c478bd9Sstevel@tonic-gate 		ber_free(p8obj_asn, 1);
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate 	if (key_octs.bv_val != NULL)
18537c478bd9Sstevel@tonic-gate 		free(key_octs.bv_val);
18547c478bd9Sstevel@tonic-gate 
18557c478bd9Sstevel@tonic-gate 	if (key_asn != NULLBER)
18567c478bd9Sstevel@tonic-gate 		ber_free(key_asn, 1);
18577c478bd9Sstevel@tonic-gate 
18587c478bd9Sstevel@tonic-gate 	return (rv);
18597c478bd9Sstevel@tonic-gate }
18607c478bd9Sstevel@tonic-gate 
18617c478bd9Sstevel@tonic-gate /*
18627c478bd9Sstevel@tonic-gate  * Decode the object key from ASN.1 format into soft_object_t.
18637c478bd9Sstevel@tonic-gate  */
18647c478bd9Sstevel@tonic-gate CK_RV
18657c478bd9Sstevel@tonic-gate soft_asn1_to_object(soft_object_t *objp, uchar_t *buf, ulong_t buf_len)
18667c478bd9Sstevel@tonic-gate {
18677c478bd9Sstevel@tonic-gate 	CK_RV 		rv = CKR_OK;
18687c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class = objp->class;
18697c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE	keytype = objp->key_type;
18707c478bd9Sstevel@tonic-gate 	private_key_obj_t *pvk;
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate 	switch (class) {
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate 	case CKO_PRIVATE_KEY:
18757c478bd9Sstevel@tonic-gate 		/* Allocate storage for Private Key Object. */
18767c478bd9Sstevel@tonic-gate 		if ((pvk = calloc(1, sizeof (private_key_obj_t))) == NULL) {
18777c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
18787c478bd9Sstevel@tonic-gate 			return (rv);
18797c478bd9Sstevel@tonic-gate 		}
18807c478bd9Sstevel@tonic-gate 
18817c478bd9Sstevel@tonic-gate 		switch (keytype) {
18827c478bd9Sstevel@tonic-gate 		case CKK_RSA:
18837c478bd9Sstevel@tonic-gate 			rv = asn1_to_rsa_pri(pvk, buf, buf_len);
18847c478bd9Sstevel@tonic-gate 			break;
18857c478bd9Sstevel@tonic-gate 
18867c478bd9Sstevel@tonic-gate 		case CKK_DSA:
18877c478bd9Sstevel@tonic-gate 			rv = asn1_to_dsa_pri(pvk, buf, buf_len);
18887c478bd9Sstevel@tonic-gate 			break;
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate 		case CKK_DH:
18917c478bd9Sstevel@tonic-gate 			rv = asn1_to_dh_pri(pvk, buf, buf_len);
18927c478bd9Sstevel@tonic-gate 			break;
18937c478bd9Sstevel@tonic-gate 
18947c478bd9Sstevel@tonic-gate 		case CKK_X9_42_DH:
18957c478bd9Sstevel@tonic-gate 			rv = asn1_to_x942_dh_pri(pvk, buf, buf_len);
18967c478bd9Sstevel@tonic-gate 			break;
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate 		default:
18997c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_NOT_SUPPORTED;
19007c478bd9Sstevel@tonic-gate 			break;
19017c478bd9Sstevel@tonic-gate 
19027c478bd9Sstevel@tonic-gate 		} /* keytype */
19037c478bd9Sstevel@tonic-gate 
19047c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
19057c478bd9Sstevel@tonic-gate 			free(pvk);
19067c478bd9Sstevel@tonic-gate 		else
19077c478bd9Sstevel@tonic-gate 			objp->object_class_u.private_key = pvk;
19087c478bd9Sstevel@tonic-gate 		break;
19097c478bd9Sstevel@tonic-gate 
19107c478bd9Sstevel@tonic-gate 	default:
19117c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_NOT_SUPPORTED;
19127c478bd9Sstevel@tonic-gate 		break;
19137c478bd9Sstevel@tonic-gate 
19147c478bd9Sstevel@tonic-gate 	} /* class */
19157c478bd9Sstevel@tonic-gate 
19167c478bd9Sstevel@tonic-gate 	return (rv);
19177c478bd9Sstevel@tonic-gate }
1918