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