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