xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/export.c (revision 1837:2a9d6afcf8f9)
117Sdinak /*
217Sdinak  * CDDL HEADER START
317Sdinak  *
417Sdinak  * The contents of this file are subject to the terms of the
5*1837Sdinak  * Common Development and Distribution License (the "License").
6*1837Sdinak  * You may not use this file except in compliance with the License.
717Sdinak  *
817Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
917Sdinak  * or http://www.opensolaris.org/os/licensing.
1017Sdinak  * See the License for the specific language governing permissions
1117Sdinak  * and limitations under the License.
1217Sdinak  *
1317Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
1417Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1517Sdinak  * If applicable, add the following below this CDDL HEADER, with the
1617Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
1717Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
1817Sdinak  *
1917Sdinak  * CDDL HEADER END
2017Sdinak  */
2117Sdinak /*
22*1837Sdinak  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2317Sdinak  * Use is subject to license terms.
2417Sdinak  */
2517Sdinak 
2617Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
2717Sdinak 
2817Sdinak /*
2917Sdinak  * This file implements the export operation for this tool.
3017Sdinak  * The basic flow of the process is to find the soft token,
3117Sdinak  * log into it, find the PKCS#11 objects in the soft token
3217Sdinak  * to be exported matching keys with their certificates, export
3317Sdinak  * them to the PKCS#12 file encrypting them with a file password
3417Sdinak  * if desired, and log out.
3517Sdinak  */
3617Sdinak 
3717Sdinak #include <stdio.h>
3817Sdinak #include <stdlib.h>
3917Sdinak #include <string.h>
4017Sdinak #include <errno.h>
4117Sdinak #include <cryptoutil.h>
4217Sdinak #include <security/cryptoki.h>
4317Sdinak #include "common.h"
4417Sdinak #include "biginteger.h"
4517Sdinak #include "osslcommon.h"
4617Sdinak #include "p12common.h"
4717Sdinak #include <openssl/pkcs12.h>
4817Sdinak 
4917Sdinak /*
5017Sdinak  * Writes OpenSSL objects to PKCS#12 file.  The PKCS#11 objects from
5117Sdinak  * the soft token need to be converted to OpenSSL structures prior
5217Sdinak  * to this call, since the PKCS#12 routines depend on that format.
5317Sdinak  * This code is patterned from OpenSSL apps that write PKCS#12 files.
5417Sdinak  *
5517Sdinak  * Note:  it's not clear from the usage of all the functions here by
5617Sdinak  * OpenSSL apps whether these functions have return values or error
5717Sdinak  * conditions that can be checked.  This function may benefit from
5817Sdinak  * a closer review at a later time.
5917Sdinak  */
6017Sdinak static int
6117Sdinak write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
6217Sdinak 	CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert,
6317Sdinak 	STACK_OF(X509) *ca_certs, int *successes, int *failures)
6417Sdinak /* ARGSUSED */
6517Sdinak {
6617Sdinak 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
6717Sdinak 	PKCS12_SAFEBAG			*bag = NULL;
6817Sdinak 	X509				*ca = NULL;
6917Sdinak 	PKCS7				*cert_authsafe = NULL;
7017Sdinak 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
7117Sdinak 	PKCS7				*key_authsafe = NULL;
7217Sdinak 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
7317Sdinak 	PKCS12				*p12_elem = NULL;
7417Sdinak 	unsigned char			*lab = NULL;
7517Sdinak 	int				lab_len = 0;
7617Sdinak 	int				i;
7717Sdinak 	int				n_writes = 0;
7817Sdinak 
7917Sdinak 	cryptodebug("inside write_objs_pkcs12");
8017Sdinak 
8117Sdinak 	/* Do not reset *successes or *failures -- keep running totals. */
8217Sdinak 
8317Sdinak 	/* If there is nothing to write to the PKCS#12 file, leave. */
8417Sdinak 	if (cert == NULL && ca_certs == NULL && priv_key == NULL) {
8517Sdinak 		cryptodebug("nothing to write to export file");
8617Sdinak 		return (0);
8717Sdinak 	}
8817Sdinak 
8917Sdinak 	/*
9017Sdinak 	 * Section 1:
9117Sdinak 	 *
9217Sdinak 	 * The first PKCS#12 container (safebag) will hold the certificates
9317Sdinak 	 * associated with this key.  The result of this section is a
9417Sdinak 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
9517Sdinak 	 * certificates, there is no point in creating the "safebag" or the
9617Sdinak 	 * "authsafe" so we go to the next section.
9717Sdinak 	 */
9817Sdinak 	if (cert != NULL || ca_certs != NULL) {
9917Sdinak 		/* Start a PKCS#12 safebag container for the certificates. */
10017Sdinak 		cryptodebug("creating certificate PKCS#12 safebag");
10117Sdinak 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
10217Sdinak 		if (bag_stack == NULL) {
10317Sdinak 			cryptoerror(LOG_STDERR, gettext(
10417Sdinak 			    "Unable to create PKCS#12 certificate bag."));
10517Sdinak 			(*failures)++;
10617Sdinak 			return (-1);
10717Sdinak 		}
10817Sdinak 
10917Sdinak 		/* Add the cert corresponding to private key to bag_stack. */
11017Sdinak 		if (cert) {
11117Sdinak 			/* Convert cert from X509 struct to PKCS#12 bag */
11217Sdinak 			cryptodebug("adding certificate to PKCS#12 safebag");
11317Sdinak 			bag = PKCS12_x5092certbag(cert);
11417Sdinak 			if (bag == NULL) {
11517Sdinak 				cryptoerror(LOG_STDERR, gettext(
11617Sdinak 				    "Unable to convert certificate to "
11717Sdinak 				    "PKCS#12 bag."));
11817Sdinak 				/* Cleanup the safebag. */
11917Sdinak 				sk_PKCS12_SAFEBAG_pop_free(bag_stack,
12017Sdinak 				    PKCS12_SAFEBAG_free);
12117Sdinak 				(*failures)++;
12217Sdinak 				return (-1);
12317Sdinak 			}
12417Sdinak 
12517Sdinak 			/* Add the key id to the certificate bag. */
12617Sdinak 			cryptodebug("add key id to PKCS#12 safebag");
12717Sdinak 			if (!PKCS12_add_localkeyid(bag, id, id_len))
12817Sdinak 				cryptodebug("error not caught");
12917Sdinak 
13017Sdinak 			/* Add the friendly name to the certificate bag. */
13117Sdinak 			if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) {
13217Sdinak 				cryptodebug(
13317Sdinak 				    "label PKCS#12 safebag with friendly name");
13417Sdinak 				if (!PKCS12_add_friendlyname(bag, (char *)lab,
13517Sdinak 				    lab_len))
13617Sdinak 					cryptodebug("error not caught");
13717Sdinak 			}
13817Sdinak 
13917Sdinak 			/* Pile it on the bag_stack. */
14017Sdinak 			if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
14117Sdinak 				cryptodebug("error not caught");
14217Sdinak 
14317Sdinak 			n_writes++;
14417Sdinak 		}
14517Sdinak 
14617Sdinak 		/* Add all the CA chain certs to the bag_stack. */
14717Sdinak 		if (ca_certs) {
14817Sdinak 			cryptodebug("adding CA certificate chain to PKCS#12 "
14917Sdinak 			    "safebag");
15017Sdinak 			/*
15117Sdinak 			 * Go through the stack of CA certs, converting each
15217Sdinak 			 * one to a PKCS#12 bag and piling them onto the
15317Sdinak 			 * bag_stack.
15417Sdinak 			 */
15517Sdinak 			for (i = 0; i < sk_X509_num(ca_certs); i++) {
15617Sdinak 				/*
15717Sdinak 				 * sk_X509_value() is macro that embeds a
15817Sdinak 				 * cast to (X509 *).  Here it translates
15917Sdinak 				 * into ((X509 *)sk_value((ca_certs), (i))).
16017Sdinak 				 * Lint is complaining about the embedded
16117Sdinak 				 * casting, and to fix it, you need to fix
16217Sdinak 				 * openssl header files.
16317Sdinak 				 */
16417Sdinak 				/* LINTED E_BAD_PTR_CAST_ALIGN */
16517Sdinak 				ca = sk_X509_value(ca_certs, i);
16617Sdinak 
16717Sdinak 				/* Convert CA cert to PKCS#12 bag. */
16817Sdinak 				cryptodebug("adding CA certificate #%d "
16917Sdinak 				    "to PKCS#12 safebag", i+1);
17017Sdinak 				bag = PKCS12_x5092certbag(ca);
17117Sdinak 				if (bag == NULL) {
17217Sdinak 					cryptoerror(LOG_STDERR, gettext(
17317Sdinak 					    "Unable to convert CA certificate "
17417Sdinak 					    "#%d to PKCS#12 bag."), i+1);
17517Sdinak 					/* Cleanup the safebag. */
17617Sdinak 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
17717Sdinak 					    PKCS12_SAFEBAG_free);
17817Sdinak 					(*failures)++;
17917Sdinak 					return (-1);
18017Sdinak 				}
18117Sdinak 
18217Sdinak 				/* Note CA certs do not have friendly name. */
18317Sdinak 
18417Sdinak 				/* Pile it onto the bag_stack. */
18517Sdinak 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
18617Sdinak 					cryptodebug("error not caught");
18717Sdinak 
18817Sdinak 				n_writes++;
18917Sdinak 			}
19017Sdinak 		}
19117Sdinak 
19217Sdinak 		/* Turn bag_stack of certs into encrypted authsafe. */
19317Sdinak 		cryptodebug("encrypt certificate PKCS#12 bag into "
19417Sdinak 		    "PKCS#7 authsafe");
19517Sdinak 		cert_authsafe = PKCS12_pack_p7encdata(
19617Sdinak 		    NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL,
19717Sdinak 		    0, PKCS12_DEFAULT_ITER, bag_stack);
19817Sdinak 
19917Sdinak 		/* Clear away this bag_stack, we're done with it. */
20017Sdinak 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
20117Sdinak 		bag_stack = NULL;
20217Sdinak 
20317Sdinak 		if (cert_authsafe == NULL) {
20417Sdinak 			cryptoerror(LOG_STDERR, gettext(
20517Sdinak 			    "Unable to PKCS#7-encrypt certificate bag."));
20617Sdinak 			(*failures)++;
20717Sdinak 			return (-1);
20817Sdinak 		}
20917Sdinak 	}
21017Sdinak 
21117Sdinak 	/*
21217Sdinak 	 * Section 2:
21317Sdinak 	 *
21417Sdinak 	 * The second PKCS#12 container (safebag) will hold the private key
21517Sdinak 	 * that goes with the certificates above.  The results of this section
21617Sdinak 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
21717Sdinak 	 * private key, there is no point in creating the "safebag" or the
21817Sdinak 	 * "authsafe" so we go to the next section.
21917Sdinak 	 */
22017Sdinak 	if (priv_key != NULL) {
22117Sdinak 		/* Make a PKCS#8 shrouded key bag. */
22217Sdinak 		cryptodebug("create PKCS#8 shrouded key out of private key");
22317Sdinak 		p8 = EVP_PKEY2PKCS8(priv_key);
22417Sdinak 		if (p8 == NULL) {
22517Sdinak 			cryptoerror(LOG_STDERR, gettext(
22617Sdinak 			    "Unable to create PKCS#8 shrouded key for "
22717Sdinak 			    "private key."));
22817Sdinak 			(*failures)++;
22917Sdinak 			return (-1);
23017Sdinak 		}
23117Sdinak 
23217Sdinak 		/* Put the shrouded key into a PKCS#12 bag. */
23317Sdinak 		cryptodebug("convert shrouded key to PKCS#12 bag");
23417Sdinak 		bag = PKCS12_MAKE_SHKEYBAG(
23517Sdinak 		    NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin,
23617Sdinak 		    -1, NULL, 0, PKCS12_DEFAULT_ITER, p8);
23717Sdinak 
23817Sdinak 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
23917Sdinak 		PKCS8_PRIV_KEY_INFO_free(p8);
24017Sdinak 		p8 = NULL;
24117Sdinak 
24217Sdinak 		if (bag == NULL) {
24317Sdinak 			cryptoerror(LOG_STDERR, gettext(
24417Sdinak 			    "Unable to convert private key to PKCS#12 bag."));
24517Sdinak 			(*failures)++;
24617Sdinak 			return (-1);
24717Sdinak 		}
24817Sdinak 
24917Sdinak 		/* Add the key id to the certificate bag. */
25017Sdinak 		cryptodebug("add key id to PKCS#12 safebag");
25117Sdinak 		if (!PKCS12_add_localkeyid(bag, id, id_len))
25217Sdinak 			cryptodebug("error not caught");
25317Sdinak 
25417Sdinak 		/* Add the cert friendly name to the private key bag. */
25517Sdinak 		if (lab != NULL) {
25617Sdinak 			cryptodebug("label PKCS#12 safebag with friendly name");
25717Sdinak 			if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len))
25817Sdinak 				cryptodebug("error not caught");
25917Sdinak 		}
26017Sdinak 
26117Sdinak 		/* Start a PKCS#12 safebag container for the private key. */
26217Sdinak 		cryptodebug("creating private key PKCS#12 safebag");
26317Sdinak 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
26417Sdinak 		if (bag_stack == NULL) {
26517Sdinak 			cryptoerror(LOG_STDERR, gettext(
26617Sdinak 			    "Unable to create PKCS#12 private key bag."));
26717Sdinak 			(*failures)++;
26817Sdinak 			return (-1);
26917Sdinak 		}
27017Sdinak 
27117Sdinak 		/* Pile on the private key on the bag_stack. */
27217Sdinak 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
27317Sdinak 			cryptodebug("error not caught");
27417Sdinak 
27517Sdinak 		/* Turn bag_stack with private key into unencrypted authsafe. */
27617Sdinak 		cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe");
27717Sdinak 		key_authsafe = PKCS12_pack_p7data(bag_stack);
27817Sdinak 
27917Sdinak 		/* Clear away this bag_stack, we're done with it. */
28017Sdinak 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
28117Sdinak 		bag_stack = NULL;
28217Sdinak 
28317Sdinak 		if (key_authsafe == NULL) {
28417Sdinak 			cryptoerror(LOG_STDERR, gettext(
28517Sdinak 			    "Unable to PKCS#7-convert private key bag."));
28617Sdinak 			(*failures)++;
28717Sdinak 			return (-1);
28817Sdinak 		}
28917Sdinak 
29017Sdinak 		n_writes++;
29117Sdinak 	}
29217Sdinak 
29317Sdinak 	/*
29417Sdinak 	 * Section 3:
29517Sdinak 	 *
29617Sdinak 	 * This is where the two PKCS#7 containers, one for the certificates
29717Sdinak 	 * and one for the private key, are put together into a PKCS#12
29817Sdinak 	 * element.  This final PKCS#12 element is written to the export file.
29917Sdinak 	 */
30017Sdinak 	/* Start a PKCS#7 stack. */
30117Sdinak 	cryptodebug("create PKCS#7 authsafe for private key and certificates");
30217Sdinak 	authsafe_stack = sk_PKCS7_new_null();
30317Sdinak 	if (authsafe_stack == NULL) {
30417Sdinak 		cryptoerror(LOG_STDERR, gettext(
30517Sdinak 		    "Unable to create PKCS#7 container for private key "
30617Sdinak 		    "and certificates."));
30717Sdinak 		(*failures)++;
30817Sdinak 		return (-1);
30917Sdinak 	}
31017Sdinak 
31117Sdinak 	/* Put certificates and private key into PKCS#7 stack. */
31217Sdinak 	if (key_authsafe != NULL) {
31317Sdinak 		cryptodebug("put private key authsafe into PKCS#7 container");
31417Sdinak 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe))
31517Sdinak 			cryptodebug("error not caught");
31617Sdinak 	}
31717Sdinak 	if (cert_authsafe != NULL) {
31817Sdinak 		cryptodebug("put certificate authsafe into PKCS#7 container");
31917Sdinak 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe))
32017Sdinak 			cryptodebug("error not caught");
32117Sdinak 	}
32217Sdinak 
32317Sdinak 	/* Create PKCS#12 element out of PKCS#7 stack. */
32417Sdinak 	cryptodebug("create PKCS#12 element for export file");
32517Sdinak 	p12_elem = PKCS12_init(NID_pkcs7_data);
32617Sdinak 	if (p12_elem == NULL) {
32717Sdinak 		cryptoerror(LOG_STDERR, gettext(
32817Sdinak 		    "Unable to create PKCS#12 element for export file."));
32917Sdinak 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
33017Sdinak 		(*failures)++;
33117Sdinak 		return (-1);
33217Sdinak 	}
33317Sdinak 
33417Sdinak 	/* Put the PKCS#7 stack into the PKCS#12 element. */
33517Sdinak 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack))
33617Sdinak 		cryptodebug("error not caught");
33717Sdinak 
33817Sdinak 	/* Clear away the PKCS#7 stack, we're done with it. */
33917Sdinak 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
34017Sdinak 	authsafe_stack = NULL;
34117Sdinak 
34217Sdinak 	/* Set the integrity MAC on the PKCS#12 element. */
34317Sdinak 	cryptodebug("setting MAC for PKCS#12 element");
34417Sdinak 	if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0,
34517Sdinak 	    PKCS12_DEFAULT_ITER, NULL))
34617Sdinak 		cryptodebug("error not caught");
34717Sdinak 
34817Sdinak 	/* Write the PKCS#12 element to the export file. */
34917Sdinak 	cryptodebug("writing PKCS#12 element to export file");
35017Sdinak 	if (!i2d_PKCS12_bio(fbio, p12_elem))
35117Sdinak 		cryptodebug("error not caught");
35217Sdinak 
35317Sdinak 	(*successes) += n_writes;
35417Sdinak 
35517Sdinak 	/* Clear away the PKCS#12 element. */
35617Sdinak 	PKCS12_free(p12_elem);
35717Sdinak 	return (0);
35817Sdinak }
35917Sdinak 
36017Sdinak /*
36117Sdinak  * Get token objects: private key, its cert, and its cert chain.
36217Sdinak  */
36317Sdinak static CK_RV
36417Sdinak get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
36517Sdinak 	CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain,
36617Sdinak 	CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len)
36717Sdinak {
36817Sdinak 	CK_RV			rv = CKR_OK;
36917Sdinak 	CK_ATTRIBUTE		keyid_attr[1] = {
37017Sdinak 		{ CKA_ID, NULL, 0 }
37117Sdinak 	    };
37217Sdinak 	static CK_OBJECT_CLASS	class = CKO_CERTIFICATE;
37317Sdinak 	static CK_CERTIFICATE_TYPE	certtype = CKC_X_509;
37417Sdinak 	CK_ATTRIBUTE		cert_attr[4] = {
37517Sdinak 		{ CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) },
37617Sdinak 		{ CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
37717Sdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
37817Sdinak 		{ CKA_ID, NULL, 0 }
37917Sdinak 	    };
38017Sdinak 	CK_ULONG	num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE);
38117Sdinak 	CK_OBJECT_HANDLE	cert = ~0UL;
38217Sdinak 	CK_ULONG		num = 0;
38317Sdinak 
38417Sdinak 	cryptodebug("inside get_token_objs");
38517Sdinak 
38617Sdinak 	/* Get the size of the object's CKA_ID field first. */
38717Sdinak 	cryptodebug("getting CKA_ID size for object 0x%x", obj);
38817Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
38917Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get size of object"
39017Sdinak 		    " key id (%s)."), pkcs11_strerror(rv));
39117Sdinak 		return (rv);
39217Sdinak 	}
39317Sdinak 
39417Sdinak 	/* Allocate the space needed for the key id. */
39517Sdinak 	if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) {
39617Sdinak 		cryptoerror(LOG_STDERR, "%s.", strerror(errno));
39717Sdinak 		return (CKR_HOST_MEMORY);
39817Sdinak 	}
39917Sdinak 
40017Sdinak 	/* Get the CKA_ID field to match obj with its cert. */
40117Sdinak 	cryptodebug("getting CKA_ID attribute for object 0x%x", obj);
40217Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
40317Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get object "
40417Sdinak 		    "key id (%s)."), pkcs11_strerror(rv));
40517Sdinak 		free(keyid_attr[0].pValue);
40617Sdinak 		return (rv);
40717Sdinak 	}
40817Sdinak 
40917Sdinak 	/* Now try to find any certs that have the same id. */
41017Sdinak 	cryptodebug("searching for certificates with same CKA_ID");
41117Sdinak 	cert_attr[3].pValue = keyid_attr[0].pValue;
41217Sdinak 	cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen;
41317Sdinak 	if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) {
41417Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to initialize "
41517Sdinak 		    "certificate search (%s)."), pkcs11_strerror(rv));
41617Sdinak 		free(keyid_attr[0].pValue);
41717Sdinak 		return (rv);
41817Sdinak 	}
41917Sdinak 
42017Sdinak 	/* Find the first cert that matches the key id. */
42117Sdinak 	if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) {
42217Sdinak 		cryptoerror(LOG_STDERR, gettext("Certificate search failed "
42317Sdinak 		    "(%s)."), pkcs11_strerror(rv));
42417Sdinak 		free(keyid_attr[0].pValue);
42517Sdinak 		return (rv);
42617Sdinak 	}
42717Sdinak 
42817Sdinak 	(void) C_FindObjectsFinal(sess);
42917Sdinak 
43017Sdinak 	*id = keyid_attr[0].pValue;
43117Sdinak 	*id_len = keyid_attr[0].ulValueLen;
43217Sdinak 
43317Sdinak 	*mate = (num == 1) ? cert : ~0UL;
43417Sdinak 
43517Sdinak 	/* We currently do not find all the certs in the chain. */
43617Sdinak 	*chain_len = 0;
43717Sdinak 	*chain = NULL;
43817Sdinak 
43917Sdinak 	return (CKR_OK);
44017Sdinak }
44117Sdinak 
44217Sdinak /*
44317Sdinak  * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM.
44417Sdinak  * "to" should be the address of a ptr init'ed to NULL to
44517Sdinak  * receive the BIGNUM, e.g.,
44617Sdinak  *	biginteger_t	from;
44717Sdinak  * 	BIGNUM	*foo = NULL;
44817Sdinak  *	cvt_bigint2bn(&from, &foo);
44917Sdinak  */
45017Sdinak static int
45117Sdinak cvt_bigint2bn(biginteger_t *from, BIGNUM **to)
45217Sdinak {
45317Sdinak 	BIGNUM	*temp = NULL;
45417Sdinak 
45517Sdinak 	cryptodebug("inside cvt_bigint2bn");
45617Sdinak 
45717Sdinak 	if (from == NULL || to == NULL)
45817Sdinak 		return (-1);
45917Sdinak 
46017Sdinak 	cryptodebug("calling BN_bin2bn");
46117Sdinak 	if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) ==
46217Sdinak 	    NULL)
46317Sdinak 		return (-1);
46417Sdinak 
46517Sdinak 	*to = temp;
46617Sdinak 	return (0);
46717Sdinak }
46817Sdinak 
46917Sdinak /*
47017Sdinak  * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure.
47117Sdinak  */
47217Sdinak static CK_RV
47317Sdinak cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
47417Sdinak {
47517Sdinak 	CK_RV		rv = CKR_OK;
47617Sdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
47717Sdinak 	RSA		*rsa = NULL;		/* OpenSSL representation */
47817Sdinak 	biginteger_t	mod = { NULL, 0 };	/* required */
47917Sdinak 	biginteger_t	pubexp = { NULL, 0 };	/* required */
48017Sdinak 	biginteger_t	priexp = { NULL, 0 };	/* optional */
48117Sdinak 	biginteger_t	prime1 = { NULL, 0 };	/* optional */
48217Sdinak 	biginteger_t	prime2 = { NULL, 0 };	/* optional */
48317Sdinak 	biginteger_t	exp1 = { NULL, 0 };	/* optional */
48417Sdinak 	biginteger_t	exp2 = { NULL, 0 };	/* optional */
48517Sdinak 	biginteger_t	coef = { NULL, 0 };	/* optional */
48617Sdinak 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
48717Sdinak 		{ CKA_MODULUS, NULL, 0 },
48817Sdinak 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
48917Sdinak 		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
49017Sdinak 		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
49117Sdinak 		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
49217Sdinak 		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
49317Sdinak 		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
49417Sdinak 		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
49517Sdinak 	    };
49617Sdinak 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
49717Sdinak 	int		i;
49817Sdinak 
49917Sdinak 	cryptodebug("inside cvt_rsa2evp_pkey");
50017Sdinak 
50117Sdinak 	cryptodebug("calling RSA_new");
50217Sdinak 	if ((rsa = RSA_new()) == NULL) {
50317Sdinak 		cryptoerror(LOG_STDERR, gettext(
50417Sdinak 		    "Unable to allocate internal RSA structure."));
50517Sdinak 		return (CKR_HOST_MEMORY);
50617Sdinak 	}
50717Sdinak 
50817Sdinak 	/* Get the sizes of the attributes we need. */
50917Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
51017Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
51117Sdinak 	    CKR_OK) {
51217Sdinak 		cryptoerror(LOG_STDERR, gettext(
51317Sdinak 		    "Unable to get RSA private key attribute sizes (%s)."),
51417Sdinak 		    pkcs11_strerror(rv));
51517Sdinak 		return (rv);
51617Sdinak 	}
51717Sdinak 
51817Sdinak 	/* Allocate memory for each attribute. */
51917Sdinak 	for (i = 0; i < count; i++) {
52017Sdinak 		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
52117Sdinak 		    rsa_pri_attrs[i].ulValueLen == 0) {
52217Sdinak 			cryptodebug("cvt_rsa2evp_pkey: *** should not happen");
52317Sdinak 			rsa_pri_attrs[i].ulValueLen = 0;
52417Sdinak 			continue;
52517Sdinak 		}
52617Sdinak 		if ((rsa_pri_attrs[i].pValue =
52717Sdinak 		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
52817Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
52917Sdinak 			return (CKR_HOST_MEMORY);
53017Sdinak 		}
53117Sdinak 	}
53217Sdinak 
53317Sdinak 	/* Now really get the attributes. */
53417Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
53517Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
53617Sdinak 	    CKR_OK) {
53717Sdinak 		cryptoerror(LOG_STDERR, gettext(
53817Sdinak 		    "Unable to get RSA private key attributes (%s)."),
53917Sdinak 		    pkcs11_strerror(rv));
54017Sdinak 		return (rv);
54117Sdinak 	}
54217Sdinak 
54317Sdinak 	/*
54417Sdinak 	 * Fill in all the temp variables.  Modulus and public exponent
54517Sdinak 	 * are required.  The rest are optional.
54617Sdinak 	 */
54717Sdinak 	i = 0;
54817Sdinak 	copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod);
54917Sdinak 	copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp);
55017Sdinak 
55117Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
55217Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
55317Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp);
55417Sdinak 	i++;
55517Sdinak 
55617Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
55717Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
55817Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1);
55917Sdinak 	i++;
56017Sdinak 
56117Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
56217Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
56317Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2);
56417Sdinak 	i++;
56517Sdinak 
56617Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
56717Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
56817Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1);
56917Sdinak 	i++;
57017Sdinak 
57117Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
57217Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
57317Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2);
57417Sdinak 	i++;
57517Sdinak 
57617Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
57717Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
57817Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef);
57917Sdinak 	i++;
58017Sdinak 
58117Sdinak 	/* Start the conversion to internal OpenSSL RSA structure. */
58217Sdinak 
58317Sdinak 	/* Modulus n */
58417Sdinak 	if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) {
58517Sdinak 		cryptoerror(LOG_STDERR, gettext(
58617Sdinak 		    "Unable to convert RSA private key modulus."));
58717Sdinak 		return (CKR_GENERAL_ERROR);
58817Sdinak 	}
58917Sdinak 
59017Sdinak 	/* Public exponent e */
59117Sdinak 	if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) {
59217Sdinak 		cryptoerror(LOG_STDERR, gettext(
59317Sdinak 		    "Unable to convert RSA private key public exponent."));
59417Sdinak 		return (CKR_GENERAL_ERROR);
59517Sdinak 	}
59617Sdinak 
59717Sdinak 	/* Private exponent e */
59817Sdinak 	if (priexp.big_value != NULL) {
59917Sdinak 		if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) {
60017Sdinak 			cryptoerror(LOG_STDERR, gettext("Unable to convert "
60117Sdinak 			    "RSA private key private exponent."));
60217Sdinak 			return (CKR_GENERAL_ERROR);
60317Sdinak 		}
60417Sdinak 	} else
60517Sdinak 		cryptodebug("no RSA private key private exponent");
60617Sdinak 
60717Sdinak 	/* Prime p */
60817Sdinak 	if (prime1.big_value != NULL) {
60917Sdinak 		if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) {
61017Sdinak 			cryptoerror(LOG_STDERR, gettext(
61117Sdinak 			    "Unable to convert RSA private key prime 1."));
61217Sdinak 			return (CKR_GENERAL_ERROR);
61317Sdinak 		}
61417Sdinak 	} else
61517Sdinak 		cryptodebug("no RSA private key prime 1");
61617Sdinak 
61717Sdinak 	/* Prime q */
61817Sdinak 	if (prime2.big_value != NULL) {
61917Sdinak 		if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) {
62017Sdinak 			cryptoerror(LOG_STDERR, gettext(
62117Sdinak 			    "Unable to convert RSA private key prime 2."));
62217Sdinak 			return (CKR_GENERAL_ERROR);
62317Sdinak 		}
62417Sdinak 	} else
62517Sdinak 		cryptodebug("no RSA private key prime 2");
62617Sdinak 
62717Sdinak 	/* Private exponent d modulo p-1 */
62817Sdinak 	if (exp1.big_value != NULL) {
62917Sdinak 		if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) {
63017Sdinak 			cryptoerror(LOG_STDERR, gettext(
63117Sdinak 			    "Unable to convert RSA private key exponent 1."));
63217Sdinak 			return (CKR_GENERAL_ERROR);
63317Sdinak 		}
63417Sdinak 	} else
63517Sdinak 		cryptodebug("no RSA private key exponent 1");
63617Sdinak 
63717Sdinak 	/* Private exponent d modulo q-1 */
63817Sdinak 	if (exp2.big_value != NULL) {
63917Sdinak 		if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) {
64017Sdinak 			cryptoerror(LOG_STDERR, gettext(
64117Sdinak 			    "Unable to convert RSA private key exponent 2."));
64217Sdinak 			return (CKR_GENERAL_ERROR);
64317Sdinak 		}
64417Sdinak 	} else
64517Sdinak 		cryptodebug("no RSA private key exponent 2");
64617Sdinak 
64717Sdinak 	/* CRT coefficient q-inverse mod p */
64817Sdinak 	if (coef.big_value != NULL) {
64917Sdinak 		if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) {
65017Sdinak 			cryptoerror(LOG_STDERR, gettext(
65117Sdinak 			    "Unable to convert RSA private key coefficient."));
65217Sdinak 			return (CKR_GENERAL_ERROR);
65317Sdinak 		}
65417Sdinak 	} else
65517Sdinak 		cryptodebug("no RSA private key coefficient");
65617Sdinak 
65717Sdinak 	/* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */
65817Sdinak 	cryptodebug("calling EVP_PKEY_new");
65917Sdinak 	if ((key = EVP_PKEY_new()) == NULL) {
66017Sdinak 		cryptoerror(LOG_STDERR, gettext(
66117Sdinak 		    "Unable to allocate internal EVP_PKEY structure."));
66217Sdinak 		return (CKR_HOST_MEMORY);
66317Sdinak 	}
66417Sdinak 
66517Sdinak 	/* Put the RSA struct into the EVP_PKEY struct and return it. */
66617Sdinak 	cryptodebug("calling EVP_PKEY_set1_RSA");
66717Sdinak 	(void) EVP_PKEY_set1_RSA(key, rsa);
66817Sdinak 
66917Sdinak 	*pk = key;
67017Sdinak 	return (CKR_OK);
67117Sdinak }
67217Sdinak 
67317Sdinak /*
67417Sdinak  * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure.
67517Sdinak  */
67617Sdinak static CK_RV
67717Sdinak cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
67817Sdinak {
67917Sdinak 	CK_RV		rv = CKR_OK;
68017Sdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
68117Sdinak 	DSA		*dsa = NULL;		/* OpenSSL representation */
68217Sdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
68317Sdinak 	biginteger_t	subprime = { NULL, 0 };	/* required */
68417Sdinak 	biginteger_t	base = { NULL, 0 };	/* required */
68517Sdinak 	biginteger_t	value = { NULL, 0 };	/* required */
68617Sdinak 	CK_ATTRIBUTE	dsa_pri_attrs[4] = {
68717Sdinak 		{ CKA_PRIME, NULL, 0 },
68817Sdinak 		{ CKA_SUBPRIME, NULL, 0 },
68917Sdinak 		{ CKA_BASE, NULL, 0 },
69017Sdinak 		{ CKA_VALUE, NULL, 0 }
69117Sdinak 	    };
69217Sdinak 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
69317Sdinak 	int		i;
69417Sdinak 
69517Sdinak 	cryptodebug("inside cvt_dsa2evp_pkey");
69617Sdinak 
69717Sdinak 	cryptodebug("calling DSA_new");
69817Sdinak 	if ((dsa = DSA_new()) == NULL) {
69917Sdinak 		cryptoerror(LOG_STDERR, gettext(
70017Sdinak 		    "Unable to allocate internal DSA structure."));
70117Sdinak 		return (CKR_HOST_MEMORY);
70217Sdinak 	}
70317Sdinak 
70417Sdinak 	/* Get the sizes of the attributes we need. */
70517Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
70617Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
70717Sdinak 	    CKR_OK) {
70817Sdinak 		cryptoerror(LOG_STDERR, gettext(
70917Sdinak 		    "Unable to get DSA private key object attributes (%s)."),
71017Sdinak 		    pkcs11_strerror(rv));
71117Sdinak 		return (rv);
71217Sdinak 	}
71317Sdinak 
71417Sdinak 	/* Allocate memory for each attribute. */
71517Sdinak 	for (i = 0; i < count; i++) {
71617Sdinak 		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
71717Sdinak 		    dsa_pri_attrs[i].ulValueLen == 0) {
71817Sdinak 			cryptodebug("cvt_dsa2evp_pkey:  *** should not happen");
71917Sdinak 			dsa_pri_attrs[i].ulValueLen = 0;
72017Sdinak 			continue;
72117Sdinak 		}
72217Sdinak 		if ((dsa_pri_attrs[i].pValue =
72317Sdinak 		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
72417Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
72517Sdinak 			return (CKR_HOST_MEMORY);
72617Sdinak 		}
72717Sdinak 	}
72817Sdinak 
72917Sdinak 	/* Now really get the attributes. */
73017Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
73117Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
73217Sdinak 	    CKR_OK) {
73317Sdinak 		cryptoerror(LOG_STDERR, gettext(
73417Sdinak 		    "Unable to get DSA private key attributes (%s)."),
73517Sdinak 		    pkcs11_strerror(rv));
73617Sdinak 		return (rv);
73717Sdinak 	}
73817Sdinak 
73917Sdinak 	/* Fill in all the temp variables.  They are all required. */
74017Sdinak 	i = 0;
74117Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime);
74217Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime);
74317Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base);
74417Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value);
74517Sdinak 
74617Sdinak 	/* Start the conversion to internal OpenSSL DSA structure. */
74717Sdinak 
74817Sdinak 	/* Prime p */
74917Sdinak 	if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) {
75017Sdinak 		cryptoerror(LOG_STDERR, gettext(
75117Sdinak 		    "Unable to convert DSA private key prime."));
75217Sdinak 		return (CKR_GENERAL_ERROR);
75317Sdinak 	}
75417Sdinak 
75517Sdinak 	/* Subprime q */
75617Sdinak 	if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) {
75717Sdinak 		cryptoerror(LOG_STDERR, gettext(
75817Sdinak 		    "Unable to convert DSA private key subprime."));
75917Sdinak 		return (CKR_GENERAL_ERROR);
76017Sdinak 	}
76117Sdinak 
76217Sdinak 	/* Base g */
76317Sdinak 	if (cvt_bigint2bn(&base, &(dsa->g)) < 0) {
76417Sdinak 		cryptoerror(LOG_STDERR, gettext(
76517Sdinak 		    "Unable to convert DSA private key base."));
76617Sdinak 		return (CKR_GENERAL_ERROR);
76717Sdinak 	}
76817Sdinak 
76917Sdinak 	/* Private key x */
77017Sdinak 	if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) {
77117Sdinak 		cryptoerror(LOG_STDERR, gettext(
77217Sdinak 		    "Unable to convert DSA private key value."));
77317Sdinak 		return (CKR_GENERAL_ERROR);
77417Sdinak 	}
77517Sdinak 
77617Sdinak 	/* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */
77717Sdinak 	cryptodebug("calling EVP_PKEY_new");
77817Sdinak 	if ((key = EVP_PKEY_new()) == NULL) {
77917Sdinak 		cryptoerror(LOG_STDERR, gettext(
78017Sdinak 		    "Unable to allocate internal EVP_PKEY structure."));
78117Sdinak 		return (CKR_HOST_MEMORY);
78217Sdinak 	}
78317Sdinak 
78417Sdinak 	/* Put the DSA struct into the EVP_PKEY struct and return it. */
78517Sdinak 	cryptodebug("calling EVP_PKEY_set1_DSA");
78617Sdinak 	(void) EVP_PKEY_set1_DSA(key, dsa);
78717Sdinak 
78817Sdinak 	*pk = key;
78917Sdinak 	return (CKR_OK);
79017Sdinak }
79117Sdinak 
79217Sdinak /*
79317Sdinak  * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure.
79417Sdinak  */
79517Sdinak static CK_RV
79617Sdinak cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
79717Sdinak {
79817Sdinak 	CK_RV		rv = CKR_OK;
79917Sdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
80017Sdinak 	DH		*dh = NULL;		/* OpenSSL representation */
80117Sdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
80217Sdinak 	biginteger_t	base = { NULL, 0 };	/* required */
80317Sdinak 	biginteger_t	value = { NULL, 0 };	/* required */
80417Sdinak 	CK_ATTRIBUTE	dh_pri_attrs[3] = {
80517Sdinak 		{ CKA_PRIME, NULL, 0 },
80617Sdinak 		{ CKA_BASE, NULL, 0 },
80717Sdinak 		{ CKA_VALUE, NULL, 0 }
80817Sdinak 	    };
80917Sdinak 	CK_ULONG	count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
81017Sdinak 	int		i;
81117Sdinak 
81217Sdinak 	cryptodebug("inside cvt_dh2evp_pkey");
81317Sdinak 
81417Sdinak 	cryptodebug("calling DH_new");
81517Sdinak 	if ((dh = DH_new()) == NULL) {
81617Sdinak 		cryptoerror(LOG_STDERR, gettext(
81717Sdinak 		    "Unable to allocate internal DH structure."));
81817Sdinak 		return (CKR_HOST_MEMORY);
81917Sdinak 	}
82017Sdinak 
82117Sdinak 	/* Get the sizes of the attributes we need. */
82217Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
82317Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
82417Sdinak 	    CKR_OK) {
82517Sdinak 		cryptoerror(LOG_STDERR, gettext(
82617Sdinak 		    "Unable to get DH private key object attributes (%s)."),
82717Sdinak 		    pkcs11_strerror(rv));
82817Sdinak 		return (rv);
82917Sdinak 	}
83017Sdinak 
83117Sdinak 	/* Allocate memory for each attribute. */
83217Sdinak 	for (i = 0; i < count; i++) {
83317Sdinak 		if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
83417Sdinak 		    dh_pri_attrs[i].ulValueLen == 0) {
83517Sdinak 			cryptodebug("cvt_dh2evp_pkey: ***should not happen");
83617Sdinak 			dh_pri_attrs[i].ulValueLen = 0;
83717Sdinak 			continue;
83817Sdinak 		}
83917Sdinak 		if ((dh_pri_attrs[i].pValue =
84017Sdinak 		    malloc(dh_pri_attrs[i].ulValueLen)) == NULL) {
84117Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
84217Sdinak 			return (CKR_HOST_MEMORY);
84317Sdinak 		}
84417Sdinak 	}
84517Sdinak 
84617Sdinak 	/* Now really get the attributes. */
84717Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
84817Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
84917Sdinak 	    CKR_OK) {
85017Sdinak 		cryptoerror(LOG_STDERR, gettext(
85117Sdinak 		    "Unable to get DH private key attributes (%s)."),
85217Sdinak 		    pkcs11_strerror(rv));
85317Sdinak 		return (rv);
85417Sdinak 	}
85517Sdinak 
85617Sdinak 	/* Fill in all the temp variables.  They are all required. */
85717Sdinak 	i = 0;
85817Sdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime);
85917Sdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base);
86017Sdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value);
86117Sdinak 
86217Sdinak 	/* Start the conversion to internal OpenSSL DH structure. */
86317Sdinak 
86417Sdinak 	/* Prime p */
86517Sdinak 	if (cvt_bigint2bn(&prime, &(dh->p)) < 0) {
86617Sdinak 		cryptoerror(LOG_STDERR, gettext(
86717Sdinak 		    "Unable to convert DH private key prime."));
86817Sdinak 		return (CKR_GENERAL_ERROR);
86917Sdinak 	}
87017Sdinak 
87117Sdinak 	/* Base g */
87217Sdinak 	if (cvt_bigint2bn(&base, &(dh->g)) < 0) {
87317Sdinak 		cryptoerror(LOG_STDERR, gettext(
87417Sdinak 		    "Unable to convert DH private key base."));
87517Sdinak 		return (CKR_GENERAL_ERROR);
87617Sdinak 	}
87717Sdinak 
87817Sdinak 	/* Private value x */
87917Sdinak 	if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) {
88017Sdinak 		cryptoerror(LOG_STDERR, gettext(
88117Sdinak 		    "Unable to convert DH private key value."));
88217Sdinak 		return (CKR_GENERAL_ERROR);
88317Sdinak 	}
88417Sdinak 
88517Sdinak 	/* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */
88617Sdinak 	cryptodebug("calling EVP_PKEY_new");
88717Sdinak 	if ((key = EVP_PKEY_new()) == NULL) {
88817Sdinak 		cryptoerror(LOG_STDERR, gettext(
88917Sdinak 		    "Unable to allocate internal EVP_PKEY structure."));
89017Sdinak 		return (CKR_HOST_MEMORY);
89117Sdinak 	}
89217Sdinak 
89317Sdinak 	/* Put the DH struct into the EVP_PKEY struct and return it. */
89417Sdinak 	cryptodebug("calling EVP_PKEY_set1_DH");
89517Sdinak 	(void) EVP_PKEY_set1_DH(key, dh);
89617Sdinak 
89717Sdinak 	*pk = key;
89817Sdinak 	return (CKR_OK);
89917Sdinak }
90017Sdinak 
90117Sdinak /*
90217Sdinak  * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure.
90317Sdinak  */
90417Sdinak static CK_RV
90517Sdinak cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
90617Sdinak {
90717Sdinak 	CK_RV			rv = CKR_OK;
90817Sdinak 	static CK_KEY_TYPE	keytype = 0;
90917Sdinak 	CK_ATTRIBUTE		keytype_attr[1] = {
91017Sdinak 		{ CKA_KEY_TYPE, &keytype, sizeof (keytype) }
91117Sdinak 	    };
91217Sdinak 
91317Sdinak 	cryptodebug("inside cvt_obj2evp_pkey");
91417Sdinak 
91517Sdinak 	/* Find out the key type to do the right conversion. */
91617Sdinak 	cryptodebug("calling C_GetAttributeValue");
91717Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) !=
91817Sdinak 	    CKR_OK) {
91917Sdinak 		cryptoerror(LOG_STDERR, gettext(
92017Sdinak 		    "Unable to get token object key type (%s)."),
92117Sdinak 		    pkcs11_strerror(rv));
92217Sdinak 		return (rv);
92317Sdinak 	}
92417Sdinak 
92517Sdinak 	switch (keytype) {
92617Sdinak 	case CKK_RSA:
92717Sdinak 		cryptodebug("converting RSA key");
92817Sdinak 		return (cvt_rsa2evp_pkey(sess, obj, pk));
92917Sdinak 	case CKK_DSA:
93017Sdinak 		cryptodebug("converting DSA key");
93117Sdinak 		return (cvt_dsa2evp_pkey(sess, obj, pk));
93217Sdinak 	case CKK_DH:
93317Sdinak 		cryptodebug("converting DH key");
93417Sdinak 		return (cvt_dh2evp_pkey(sess, obj, pk));
93517Sdinak 	default:
93617Sdinak 		cryptoerror(LOG_STDERR, gettext(
93717Sdinak 		    "Private key type 0x%02x conversion not supported."),
93817Sdinak 		    keytype);
93917Sdinak 		return (CKR_GENERAL_ERROR);
94017Sdinak 	}
94117Sdinak }
94217Sdinak 
94317Sdinak /*
94417Sdinak  * Convert PKCS#11 certificate object to OpenSSL X509 structure.
94517Sdinak  */
94617Sdinak static CK_RV
94717Sdinak cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c)
94817Sdinak {
94917Sdinak 	CK_RV			rv = CKR_OK;
95017Sdinak 	X509			*cert = NULL;	/* OpenSSL representation */
95117Sdinak 	X509			*temp_cert = NULL;
95217Sdinak 	CK_BYTE			*subject = NULL;
95317Sdinak 	CK_ULONG		subject_len = 0;
95417Sdinak 	CK_BYTE			*value = NULL;
95517Sdinak 	CK_ULONG		value_len = 0;
95617Sdinak 	CK_BYTE			*label = NULL;
95717Sdinak 	CK_ULONG		label_len = 0;
95817Sdinak 	CK_BYTE			*id = NULL;
95917Sdinak 	CK_ULONG		id_len = 0;
96017Sdinak 	CK_BYTE			*issuer = NULL;
96117Sdinak 	CK_ULONG		issuer_len = 0;
96217Sdinak 	CK_BYTE			*serial = NULL;
96317Sdinak 	CK_ULONG		serial_len = 0;
96417Sdinak 	CK_ATTRIBUTE		cert_attrs[6] = {
96517Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* required */
96617Sdinak 		{ CKA_VALUE, NULL, 0 },			/* required */
96717Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
96817Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
96917Sdinak 		{ CKA_ISSUER, NULL, 0 },		/* optional */
97017Sdinak 		{ CKA_SERIAL_NUMBER, NULL, 0 }		/* optional */
97117Sdinak 	    };
97217Sdinak 	CK_ULONG	count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
97317Sdinak 	int		i = 0;
97417Sdinak 	X509_NAME	*ssl_subject = NULL;
97517Sdinak 	X509_NAME	*ssl_issuer = NULL;
97617Sdinak 	ASN1_INTEGER	*ssl_serial = NULL;
97717Sdinak 
97817Sdinak 	cryptodebug("inside cvt_cert2x509");
97917Sdinak 
98017Sdinak 	cryptodebug("calling X509_new");
98117Sdinak 	if ((cert = X509_new()) == NULL) {
98217Sdinak 		cryptoerror(LOG_STDERR, gettext(
98317Sdinak 		    "Unable to allocate internal X509 structure."));
98417Sdinak 		return (CKR_HOST_MEMORY);
98517Sdinak 	}
98617Sdinak 
98717Sdinak 	/* Get the sizes of the attributes we need. */
98817Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
98917Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
99017Sdinak 	    CKR_OK) {
99117Sdinak 		cryptoerror(LOG_STDERR, gettext(
99217Sdinak 		    "Unable to get certificate attribute sizes (%s)."),
99317Sdinak 		    pkcs11_strerror(rv));
99417Sdinak 		return (rv);
99517Sdinak 	}
99617Sdinak 
99717Sdinak 	/* Allocate memory for each attribute. */
99817Sdinak 	for (i = 0; i < count; i++) {
99917Sdinak 		if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 ||
100017Sdinak 		    cert_attrs[i].ulValueLen == 0) {
100117Sdinak 			cryptodebug("cvt_cert2x509:  *** should not happen");
100217Sdinak 			cert_attrs[i].ulValueLen = 0;
100317Sdinak 			continue;
100417Sdinak 		}
100517Sdinak 		if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen))
100617Sdinak 		    == NULL) {
100717Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
100817Sdinak 			return (CKR_HOST_MEMORY);
100917Sdinak 		}
101017Sdinak 	}
101117Sdinak 
101217Sdinak 	/* Now really get the attributes. */
101317Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
101417Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
101517Sdinak 	    CKR_OK) {
101617Sdinak 		cryptoerror(LOG_STDERR, gettext(
101717Sdinak 		    "Unable to get certificate attributes (%s)."),
101817Sdinak 		    pkcs11_strerror(rv));
101917Sdinak 		return (rv);
102017Sdinak 	}
102117Sdinak 
102217Sdinak 	/*
102317Sdinak 	 * Fill in all the temp variables.  Subject and value are required.
102417Sdinak 	 * The rest are optional.
102517Sdinak 	 */
102617Sdinak 	i = 0;
102717Sdinak 	copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len);
102817Sdinak 	copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len);
102917Sdinak 
103017Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
103117Sdinak 	    cert_attrs[i].ulValueLen != 0)
103217Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &label, &label_len);
103317Sdinak 	i++;
103417Sdinak 
103517Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
103617Sdinak 	    cert_attrs[i].ulValueLen != 0)
103717Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &id, &id_len);
103817Sdinak 	i++;
103917Sdinak 
104017Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
104117Sdinak 	    cert_attrs[i].ulValueLen != 0)
104217Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len);
104317Sdinak 	i++;
104417Sdinak 
104517Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
104617Sdinak 	    cert_attrs[i].ulValueLen != 0)
104717Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len);
104817Sdinak 	i++;
104917Sdinak 
105017Sdinak 	/* Start the conversion to internal OpenSSL X509 structure. */
105117Sdinak 
105217Sdinak 	/* Subject name (required) */
105317Sdinak 	cryptodebug("calling d2i_X509_NAME for subject name");
105417Sdinak 	if ((ssl_subject = d2i_X509_NAME(NULL, &subject, subject_len)) ==
105517Sdinak 	    NULL) {
105617Sdinak 		cryptoerror(LOG_STDERR, gettext(
105717Sdinak 		    "Unable to convert certificate subject name."));
105817Sdinak 		return (CKR_GENERAL_ERROR);
105917Sdinak 	}
106017Sdinak 	cryptodebug("calling X509_set_subject_name");
106117Sdinak 	if (!X509_set_subject_name(cert, ssl_subject)) {
106217Sdinak 		cryptoerror(LOG_STDERR, gettext(
106317Sdinak 		    "Unable to pack certificate subject name entries."));
106417Sdinak 		return (CKR_GENERAL_ERROR);
106517Sdinak 	}
106617Sdinak 
106717Sdinak 	/* Label (optional) */
106817Sdinak 	cryptodebug("calling X509_alias_set1");
106917Sdinak 	if (!X509_alias_set1(cert, label, label_len))
107017Sdinak 		cryptodebug("error not caught");
107117Sdinak 
107217Sdinak 	/* Id (optional) */
107317Sdinak 	cryptodebug("calling X509_keyid_set1");
107417Sdinak 	if (!X509_keyid_set1(cert, id, id_len))
107517Sdinak 		cryptodebug("error not caught");
107617Sdinak 
107717Sdinak 	/* Issuer name (optional) */
107817Sdinak 	cryptodebug("calling d2i_X509_NAME for issuer name");
107917Sdinak 	if ((ssl_issuer = d2i_X509_NAME(NULL, &issuer, issuer_len)) == NULL) {
108017Sdinak 		cryptoerror(LOG_STDERR, gettext(
108117Sdinak 		    "Unable to convert certificate issuer name."));
108217Sdinak 		return (CKR_GENERAL_ERROR);
108317Sdinak 	}
108417Sdinak 	cryptodebug("calling X509_set_issuer_name");
108517Sdinak 	if (!X509_set_issuer_name(cert, ssl_issuer)) {
108617Sdinak 		cryptoerror(LOG_STDERR, gettext(
108717Sdinak 		    "Unable to pack certificate issuer name entries."));
108817Sdinak 		return (CKR_GENERAL_ERROR);
108917Sdinak 	}
109017Sdinak 
109117Sdinak 	/* Serial number (optional) */
1092*1837Sdinak 	cryptodebug("calling OPENSSL_malloc() for serial number");
1093*1837Sdinak 	if ((ssl_serial = OPENSSL_malloc(sizeof (ASN1_INTEGER))) == NULL) {
109417Sdinak 		cryptoerror(LOG_STDERR, gettext(
109517Sdinak 		    "Unable to convert certificate serial number."));
1096*1837Sdinak 		return (CKR_HOST_MEMORY);
109717Sdinak 	}
1098*1837Sdinak 	ssl_serial->length = serial_len;
1099*1837Sdinak 	ssl_serial->type = (serial[0] & 0x80) ? V_ASN1_NEG_INTEGER :
1100*1837Sdinak 	    V_ASN1_INTEGER;
1101*1837Sdinak 	ssl_serial->data = serial;
1102*1837Sdinak 	ssl_serial->flags = 0;
110317Sdinak 	cryptodebug("calling X509_set_serialNumber");
110417Sdinak 	if (!X509_set_serialNumber(cert, ssl_serial))
110517Sdinak 		cryptodebug("error not caught");
110617Sdinak 
110717Sdinak 	/*
110817Sdinak 	 * Value (required)
110917Sdinak 	 *
111017Sdinak 	 * The rest of this code takes the CKA_VALUE attribute, converts
111117Sdinak 	 * it into a temp OpenSSL X509 structure and picks out the rest
111217Sdinak 	 * of the fields we need to convert it back into the current X509
111317Sdinak 	 * structure that will get exported.  The reason we don't just
111417Sdinak 	 * start with CKA_VALUE is because while the object was in the
111517Sdinak 	 * softtoken, it is possible that some of its attributes changed.
111617Sdinak 	 * Those changes would not appear in CKA_VALUE and would be lost
111717Sdinak 	 * if we started with CKA_VALUE that was saved originally.
111817Sdinak 	 */
111917Sdinak 	cryptodebug("calling d2i_X509 for cert value");
112017Sdinak 	if ((temp_cert = d2i_X509(NULL, &value, value_len)) == NULL) {
112117Sdinak 		cryptoerror(LOG_STDERR, gettext(
112217Sdinak 		    "Unable to convert main certificate values."));
112317Sdinak 		return (CKR_GENERAL_ERROR);
112417Sdinak 	}
112517Sdinak 
112617Sdinak 	/* Transfer these values from temp_cert to cert. */
112717Sdinak 	cryptodebug("calling X509_set_version/X509_get_version");
112817Sdinak 	if (!X509_set_version(cert, X509_get_version(temp_cert)))
112917Sdinak 		cryptodebug("error not caught");
113017Sdinak 
113117Sdinak 	cryptodebug("calling X509_set_notBefore/X509_get_notBefore");
113217Sdinak 	if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert)))
113317Sdinak 		cryptodebug("error not caught");
113417Sdinak 
113517Sdinak 	cryptodebug("calling X509_set_notAfter/X509_get_notAfter");
113617Sdinak 	if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert)))
113717Sdinak 		cryptodebug("error not caught");
113817Sdinak 
113917Sdinak 	cryptodebug("calling X509_set_pubkey/X509_get_pubkey");
114017Sdinak 	if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert)))
114117Sdinak 		cryptodebug("error not caught");
114217Sdinak 
114317Sdinak 	/*
114417Sdinak 	 * These don't get transfered from temp_cert to cert.
114517Sdinak 	 * It -appears- that they may get regenerated as needed.
114617Sdinak 	 *
114717Sdinak 	 * cert->cert_info->signature = dup(temp_cert->cert_info->signature);
114817Sdinak 	 * cert->sig_alg = dup(temp_cert->sig_alg);
114917Sdinak 	 * cert->signature = dup(temp_cert->signature);
115017Sdinak 	 * cert->skid = dup(temp_cert->skid);
115117Sdinak 	 * cert->akid = dup(temp_cert->akid);
115217Sdinak 	 */
115317Sdinak 
115417Sdinak 	*c = cert;
115517Sdinak 	return (CKR_OK);
115617Sdinak }
115717Sdinak 
115817Sdinak static CK_RV
115917Sdinak convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
116017Sdinak 	CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len,
116117Sdinak 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
116217Sdinak {
116317Sdinak 	CK_RV		rv = CKR_OK;
116417Sdinak 	EVP_PKEY	*pk = NULL;
116517Sdinak 	X509		*c = NULL;
116617Sdinak 	X509		*one_ca = NULL;
116717Sdinak 	STACK_OF(X509)	*ch = NULL;
116817Sdinak 	int		i;
116917Sdinak 
117017Sdinak 	cryptodebug("inside convert_token_objs");
117117Sdinak 
117217Sdinak 	if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK)
117317Sdinak 		return (rv);
117417Sdinak 
117517Sdinak 	if (mate != ~0UL) {
117617Sdinak 		cryptodebug("converting cert corresponding to private key");
117717Sdinak 		if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK)
117817Sdinak 			return (rv);
117917Sdinak 	}
118017Sdinak 
118117Sdinak 	if (chain_len != 0) {
118217Sdinak 		cryptodebug("converting ca chain of %d certs corresponding "
118317Sdinak 		    "to private key", chain_len);
118417Sdinak 		ch = sk_X509_new_null();
118517Sdinak 		for (i = 0; i < chain_len; i++) {
118617Sdinak 			if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) !=
118717Sdinak 			    CKR_OK) {
118817Sdinak 				return (rv);
118917Sdinak 			}
119017Sdinak 			if (!sk_X509_push(ch, one_ca))
119117Sdinak 				cryptodebug("error not caught");
119217Sdinak 		}
119317Sdinak 	}
119417Sdinak 
119517Sdinak 	*priv_key = pk;
119617Sdinak 	*cert = (mate != ~0UL) ? c : NULL;
119717Sdinak 	*ca = (chain_len != 0) ? ch : NULL;
119817Sdinak 	return (CKR_OK);
119917Sdinak }
120017Sdinak 
120117Sdinak /*
120217Sdinak  * Export objects from token to PKCS#12 file.
120317Sdinak  */
120417Sdinak int
120517Sdinak pk_export(int argc, char *argv[])
120617Sdinak {
1207864Sdinak 	int		opt;
1208864Sdinak 	extern int	optind_av;
1209864Sdinak 	extern char	*optarg_av;
1210864Sdinak 	char		*token_spec = NULL;
121117Sdinak 	char		*token_name = NULL;
121217Sdinak 	char		*manuf_id = NULL;
121317Sdinak 	char		*serial_no = NULL;
121417Sdinak 	char		full_name[FULL_NAME_LEN];
121517Sdinak 	char		*filename = NULL;
121617Sdinak 	CK_SLOT_ID	slot_id;
121717Sdinak 	CK_FLAGS	pin_state;
121817Sdinak 	CK_UTF8CHAR_PTR	pin = NULL;
121917Sdinak 	CK_ULONG	pinlen = 0;
122017Sdinak 	CK_UTF8CHAR_PTR	pk12pin = NULL;
122117Sdinak 	CK_ULONG	pk12pinlen = 0;
122217Sdinak 	CK_SESSION_HANDLE	sess;
122317Sdinak 	BIO		*fbio = NULL;
122417Sdinak 	EVP_PKEY	*priv_key = NULL;
122517Sdinak 	X509		*cert = NULL;
122617Sdinak 	STACK_OF(X509)	*ca = NULL;
122717Sdinak 	CK_RV		rv = CKR_OK;
122817Sdinak 	CK_OBJECT_HANDLE	*objs = NULL;
122917Sdinak 	CK_ULONG	num_objs = 0;
123017Sdinak 	CK_OBJECT_HANDLE	mate = ~0UL;
123117Sdinak 	CK_OBJECT_HANDLE	*chain = NULL;
123217Sdinak 	CK_ULONG	chain_len;
123317Sdinak 	CK_BYTE		*id = NULL;
123417Sdinak 	CK_ULONG	id_len = 0;
123517Sdinak 	int		i = 0;
123617Sdinak 	int		good_ones = 0, bad_ones = 0;	/* running totals */
123717Sdinak 
123817Sdinak 	cryptodebug("inside pk_export");
123917Sdinak 
1240864Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
1241864Sdinak 	while ((opt = getopt_av(argc, argv, "T:(token)o:(outfile)")) != EOF) {
1242864Sdinak 		switch (opt) {
1243864Sdinak 		case 'T':	/* token specifier */
1244864Sdinak 			if (token_spec)
1245864Sdinak 				return (PK_ERR_USAGE);
1246864Sdinak 			token_spec = optarg_av;
1247864Sdinak 			break;
1248864Sdinak 		case 'o':	/* output file name */
1249864Sdinak 			if (filename)
1250864Sdinak 				return (PK_ERR_USAGE);
1251864Sdinak 			filename = optarg_av;
1252864Sdinak 			break;
1253864Sdinak 		default:
1254864Sdinak 			return (PK_ERR_USAGE);
1255864Sdinak 			break;
1256864Sdinak 		}
1257864Sdinak 	}
125817Sdinak 
1259864Sdinak 	/* If nothing is specified, default is to use softtoken. */
1260864Sdinak 	if (token_spec == NULL) {
1261864Sdinak 		token_name = SOFT_TOKEN_LABEL;
1262864Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
1263864Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
1264864Sdinak 	} else {
1265864Sdinak 		/*
1266864Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
1267864Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
1268864Sdinak 		 */
1269864Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
1270864Sdinak 		    &serial_no) < 0)
1271864Sdinak 			return (PK_ERR_USAGE);
1272864Sdinak 	}
1273864Sdinak 
1274864Sdinak 	/* Filename arg is required. */
1275864Sdinak 	if (filename == NULL)
127617Sdinak 		return (PK_ERR_USAGE);
127717Sdinak 
1278864Sdinak 	/* No additional args allowed. */
1279864Sdinak 	argc -= optind_av;
1280864Sdinak 	argv += optind_av;
1281864Sdinak 	if (argc)
1282864Sdinak 		return (PK_ERR_USAGE);
128317Sdinak 	/* Done parsing command line options. */
128417Sdinak 
128517Sdinak 	/* Check if the file exists and might be overwritten. */
128617Sdinak 	if (access(filename, F_OK) == 0) {
128717Sdinak 		cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, "
128817Sdinak 		    "will be overwritten."), filename);
128917Sdinak 		if (yesno(gettext("Continue with export? "),
129017Sdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
129117Sdinak 			return (0);
129217Sdinak 		}
129317Sdinak 	}
129417Sdinak 
129517Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
129617Sdinak 
129717Sdinak 	/* Find the slot with token. */
129817Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
129917Sdinak 	    &pin_state)) != CKR_OK) {
130017Sdinak 		cryptoerror(LOG_STDERR, gettext(
130117Sdinak 		    "Unable to find token %s (%s)."), full_name,
130217Sdinak 		    pkcs11_strerror(rv));
130317Sdinak 		return (PK_ERR_PK11);
130417Sdinak 	}
130517Sdinak 
130617Sdinak 	/* Get the user's PIN. */
130717Sdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
130817Sdinak 	    &pinlen)) != CKR_OK) {
130917Sdinak 		cryptoerror(LOG_STDERR, gettext(
131017Sdinak 		    "Unable to get token passphrase (%s)."),
131117Sdinak 		    pkcs11_strerror(rv));
131217Sdinak 		quick_finish(NULL);
131317Sdinak 		return (PK_ERR_PK11);
131417Sdinak 	}
131517Sdinak 
131617Sdinak 	/* Assume user must be logged in R/W to export objects from token. */
131717Sdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
131817Sdinak 	    CKR_OK) {
131917Sdinak 		cryptoerror(LOG_STDERR,
132017Sdinak 		    gettext("Unable to log into token (%s)."),
132117Sdinak 		    pkcs11_strerror(rv));
132217Sdinak 		quick_finish(sess);
132317Sdinak 		return (PK_ERR_PK11);
132417Sdinak 	}
132517Sdinak 
132617Sdinak 	/* Collect all private keys first. */
132717Sdinak 	if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL,
132817Sdinak 	    &objs, &num_objs)) != CKR_OK) {
132917Sdinak 		cryptoerror(LOG_STDERR, gettext(
133017Sdinak 		    "Unable to retrieve private key token objects (%s)."),
133117Sdinak 		    pkcs11_strerror(rv));
133217Sdinak 		quick_finish(sess);
133317Sdinak 		return (PK_ERR_PK11);
133417Sdinak 	}
133517Sdinak 
133617Sdinak 	/* Nothing to do? */
133717Sdinak 	if (num_objs == 0) {
133817Sdinak 		cryptoerror(LOG_STDERR, gettext("No objects found."));
133917Sdinak 		quick_finish(sess);
134017Sdinak 		return (0);
134117Sdinak 	}
134217Sdinak 
134317Sdinak 	/* Setup OpenSSL context. */
134417Sdinak 	PKTOOL_setup_openssl();
134517Sdinak 
134617Sdinak 	/* Create PKCS#12 file. */
134717Sdinak 	if ((create_pkcs12(filename, &fbio)) < 0) {
134817Sdinak 		cryptoerror(LOG_STDERR, gettext("No export file created."));
134917Sdinak 		quick_finish(sess);
135017Sdinak 		return (PK_ERR_SYSTEM);
135117Sdinak 	}
135217Sdinak 
135317Sdinak 	/* Get the PIN for the PKCS#12 export file. */
135417Sdinak 	if ((rv = get_pin(gettext("Create export file passphrase:"), gettext(
135517Sdinak 	    "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) !=
135617Sdinak 	    CKR_OK) {
135717Sdinak 		cryptoerror(LOG_STDERR,
135817Sdinak 		    gettext("Unable to get export file passphrase (%s)."),
135917Sdinak 		    pkcs11_strerror(rv));
136017Sdinak 		close_pkcs12(fbio);
136117Sdinak 		quick_finish(sess);
136217Sdinak 		return (PK_ERR_PK11);
136317Sdinak 	}
136417Sdinak 
136517Sdinak 	for (i = 0; i < num_objs; i++) {
136617Sdinak 		/* Get a private key and its certificate and CA chain. */
136717Sdinak 		if ((rv = get_token_objs(sess, objs[i], &mate, &chain,
136817Sdinak 		    &chain_len, &id, &id_len)) != CKR_OK) {
136917Sdinak 			/*
137017Sdinak 			 * Note this "rv" is either CKR_OK or !CKR_OK.  The
137117Sdinak 			 * real error codes/messages are handled inside
137217Sdinak 			 * read_token_objs().
137317Sdinak 			 */
137417Sdinak 			cryptoerror(LOG_STDERR,
137517Sdinak 			    gettext("Unable to get token objects."));
137617Sdinak 			free(id);
137717Sdinak 			close_pkcs12(fbio);
137817Sdinak 			quick_finish(sess);
137917Sdinak 			return (PK_ERR_PK11);
138017Sdinak 		}
138117Sdinak 
138217Sdinak 		/* Convert to OpenSSL equivalents. */
138317Sdinak 		if ((rv = convert_token_objs(sess, objs[i], mate, chain,
138417Sdinak 		    chain_len, &priv_key, &cert, &ca)) != CKR_OK) {
138517Sdinak 			/*
138617Sdinak 			 * Note this "rv" is either CKR_OK or !CKR_OK.  The
138717Sdinak 			 * real error codes/messages are handled inside
138817Sdinak 			 * read_token_objs().
138917Sdinak 			 */
139017Sdinak 			cryptoerror(LOG_STDERR,
139117Sdinak 			    gettext("Unable to convert token objects."));
139217Sdinak 			free(id);
139317Sdinak 			close_pkcs12(fbio);
139417Sdinak 			quick_finish(sess);
139517Sdinak 			return (PK_ERR_PK11);
139617Sdinak 		}
139717Sdinak 
139817Sdinak 		/*
139917Sdinak 		 * When exporting of cert chains is implemented, these
140017Sdinak 		 * messages should be updated accordingly.
140117Sdinak 		 */
140217Sdinak 		if (mate == ~0UL)
140317Sdinak 			(void) fprintf(stdout, gettext(
140417Sdinak 			    "Writing object #%d...\n"), i+1);
140517Sdinak 		else
140617Sdinak 			(void) fprintf(stdout, gettext("Writing object #%d "
140717Sdinak 			    "and its certificate...\n"), i+1);
140817Sdinak 
140917Sdinak 		/* Write object and its certs to the PKCS#12 export file. */
141017Sdinak 		if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len,
141117Sdinak 		    priv_key, cert, ca, &good_ones, &bad_ones) < 0) {
141217Sdinak 			cryptoerror(LOG_STDERR, gettext(
141317Sdinak 			    "Unable to write object #%d to export file."), i+1);
141417Sdinak 			sk_X509_pop_free(ca, X509_free);
141517Sdinak 			free(id);
141617Sdinak 			close_pkcs12(fbio);
141717Sdinak 			quick_finish(sess);
141817Sdinak 			return (PK_ERR_OPENSSL);
141917Sdinak 		}
142017Sdinak 
142117Sdinak 		/* Destroy key id and CA cert chain, done with them. */
142217Sdinak 		free(id);
142317Sdinak 		id = NULL;
142417Sdinak 		sk_X509_pop_free(ca, X509_free);
142517Sdinak 		ca = NULL;
142617Sdinak 	}
142717Sdinak 
142817Sdinak 	(void) fprintf(stdout, gettext(
142917Sdinak 	    "%d token objects exported, %d errors occurred.\n"),
143017Sdinak 	    good_ones, bad_ones);
143117Sdinak 
143217Sdinak 	/* Close PKCS#12 file. */
143317Sdinak 	close_pkcs12(fbio);
143417Sdinak 
143517Sdinak 	/* Clean up. */
143617Sdinak 	quick_finish(sess);
143717Sdinak 	return (0);
143817Sdinak }
1439