17711facfSdinak /*
27711facfSdinak  * CDDL HEADER START
37711facfSdinak  *
47711facfSdinak  * The contents of this file are subject to the terms of the
57711facfSdinak  * Common Development and Distribution License, Version 1.0 only
67711facfSdinak  * (the "License").  You may not use this file except in compliance
77711facfSdinak  * with the License.
87711facfSdinak  *
97711facfSdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107711facfSdinak  * or http://www.opensolaris.org/os/licensing.
117711facfSdinak  * See the License for the specific language governing permissions
127711facfSdinak  * and limitations under the License.
137711facfSdinak  *
147711facfSdinak  * When distributing Covered Code, include this CDDL HEADER in each
157711facfSdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167711facfSdinak  * If applicable, add the following below this CDDL HEADER, with the
177711facfSdinak  * fields enclosed by brackets "[]" replaced with your own identifying
187711facfSdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
197711facfSdinak  *
207711facfSdinak  * CDDL HEADER END
217711facfSdinak  */
227711facfSdinak /*
237711facfSdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247711facfSdinak  * Use is subject to license terms.
257711facfSdinak  */
267711facfSdinak 
277711facfSdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
287711facfSdinak 
297711facfSdinak /*
307711facfSdinak  * This file implements the export operation for this tool.
317711facfSdinak  * The basic flow of the process is to find the soft token,
327711facfSdinak  * log into it, find the PKCS#11 objects in the soft token
337711facfSdinak  * to be exported matching keys with their certificates, export
347711facfSdinak  * them to the PKCS#12 file encrypting them with a file password
357711facfSdinak  * if desired, and log out.
367711facfSdinak  */
377711facfSdinak 
387711facfSdinak #include <stdio.h>
397711facfSdinak #include <stdlib.h>
407711facfSdinak #include <string.h>
417711facfSdinak #include <errno.h>
427711facfSdinak #include <cryptoutil.h>
437711facfSdinak #include <security/cryptoki.h>
447711facfSdinak #include "common.h"
457711facfSdinak #include "biginteger.h"
467711facfSdinak #include "osslcommon.h"
477711facfSdinak #include "p12common.h"
487711facfSdinak #include <openssl/pkcs12.h>
497711facfSdinak 
507711facfSdinak /*
517711facfSdinak  * Writes OpenSSL objects to PKCS#12 file.  The PKCS#11 objects from
527711facfSdinak  * the soft token need to be converted to OpenSSL structures prior
537711facfSdinak  * to this call, since the PKCS#12 routines depend on that format.
547711facfSdinak  * This code is patterned from OpenSSL apps that write PKCS#12 files.
557711facfSdinak  *
567711facfSdinak  * Note:  it's not clear from the usage of all the functions here by
577711facfSdinak  * OpenSSL apps whether these functions have return values or error
587711facfSdinak  * conditions that can be checked.  This function may benefit from
597711facfSdinak  * a closer review at a later time.
607711facfSdinak  */
617711facfSdinak static int
627711facfSdinak write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
637711facfSdinak 	CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert,
647711facfSdinak 	STACK_OF(X509) *ca_certs, int *successes, int *failures)
657711facfSdinak /* ARGSUSED */
667711facfSdinak {
677711facfSdinak 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
687711facfSdinak 	PKCS12_SAFEBAG			*bag = NULL;
697711facfSdinak 	X509				*ca = NULL;
707711facfSdinak 	PKCS7				*cert_authsafe = NULL;
717711facfSdinak 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
727711facfSdinak 	PKCS7				*key_authsafe = NULL;
737711facfSdinak 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
747711facfSdinak 	PKCS12				*p12_elem = NULL;
757711facfSdinak 	unsigned char			*lab = NULL;
767711facfSdinak 	int				lab_len = 0;
777711facfSdinak 	int				i;
787711facfSdinak 	int				n_writes = 0;
797711facfSdinak 
807711facfSdinak 	cryptodebug("inside write_objs_pkcs12");
817711facfSdinak 
827711facfSdinak 	/* Do not reset *successes or *failures -- keep running totals. */
837711facfSdinak 
847711facfSdinak 	/* If there is nothing to write to the PKCS#12 file, leave. */
857711facfSdinak 	if (cert == NULL && ca_certs == NULL && priv_key == NULL) {
867711facfSdinak 		cryptodebug("nothing to write to export file");
877711facfSdinak 		return (0);
887711facfSdinak 	}
897711facfSdinak 
907711facfSdinak 	/*
917711facfSdinak 	 * Section 1:
927711facfSdinak 	 *
937711facfSdinak 	 * The first PKCS#12 container (safebag) will hold the certificates
947711facfSdinak 	 * associated with this key.  The result of this section is a
957711facfSdinak 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
967711facfSdinak 	 * certificates, there is no point in creating the "safebag" or the
977711facfSdinak 	 * "authsafe" so we go to the next section.
987711facfSdinak 	 */
997711facfSdinak 	if (cert != NULL || ca_certs != NULL) {
1007711facfSdinak 		/* Start a PKCS#12 safebag container for the certificates. */
1017711facfSdinak 		cryptodebug("creating certificate PKCS#12 safebag");
1027711facfSdinak 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
1037711facfSdinak 		if (bag_stack == NULL) {
1047711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
1057711facfSdinak 			    "Unable to create PKCS#12 certificate bag."));
1067711facfSdinak 			(*failures)++;
1077711facfSdinak 			return (-1);
1087711facfSdinak 		}
1097711facfSdinak 
1107711facfSdinak 		/* Add the cert corresponding to private key to bag_stack. */
1117711facfSdinak 		if (cert) {
1127711facfSdinak 			/* Convert cert from X509 struct to PKCS#12 bag */
1137711facfSdinak 			cryptodebug("adding certificate to PKCS#12 safebag");
1147711facfSdinak 			bag = PKCS12_x5092certbag(cert);
1157711facfSdinak 			if (bag == NULL) {
1167711facfSdinak 				cryptoerror(LOG_STDERR, gettext(
1177711facfSdinak 				    "Unable to convert certificate to "
1187711facfSdinak 				    "PKCS#12 bag."));
1197711facfSdinak 				/* Cleanup the safebag. */
1207711facfSdinak 				sk_PKCS12_SAFEBAG_pop_free(bag_stack,
1217711facfSdinak 				    PKCS12_SAFEBAG_free);
1227711facfSdinak 				(*failures)++;
1237711facfSdinak 				return (-1);
1247711facfSdinak 			}
1257711facfSdinak 
1267711facfSdinak 			/* Add the key id to the certificate bag. */
1277711facfSdinak 			cryptodebug("add key id to PKCS#12 safebag");
1287711facfSdinak 			if (!PKCS12_add_localkeyid(bag, id, id_len))
1297711facfSdinak 				cryptodebug("error not caught");
1307711facfSdinak 
1317711facfSdinak 			/* Add the friendly name to the certificate bag. */
1327711facfSdinak 			if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) {
1337711facfSdinak 				cryptodebug(
1347711facfSdinak 				    "label PKCS#12 safebag with friendly name");
1357711facfSdinak 				if (!PKCS12_add_friendlyname(bag, (char *)lab,
1367711facfSdinak 				    lab_len))
1377711facfSdinak 					cryptodebug("error not caught");
1387711facfSdinak 			}
1397711facfSdinak 
1407711facfSdinak 			/* Pile it on the bag_stack. */
1417711facfSdinak 			if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
1427711facfSdinak 				cryptodebug("error not caught");
1437711facfSdinak 
1447711facfSdinak 			n_writes++;
1457711facfSdinak 		}
1467711facfSdinak 
1477711facfSdinak 		/* Add all the CA chain certs to the bag_stack. */
1487711facfSdinak 		if (ca_certs) {
1497711facfSdinak 			cryptodebug("adding CA certificate chain to PKCS#12 "
1507711facfSdinak 			    "safebag");
1517711facfSdinak 			/*
1527711facfSdinak 			 * Go through the stack of CA certs, converting each
1537711facfSdinak 			 * one to a PKCS#12 bag and piling them onto the
1547711facfSdinak 			 * bag_stack.
1557711facfSdinak 			 */
1567711facfSdinak 			for (i = 0; i < sk_X509_num(ca_certs); i++) {
1577711facfSdinak 				/*
1587711facfSdinak 				 * sk_X509_value() is macro that embeds a
1597711facfSdinak 				 * cast to (X509 *).  Here it translates
1607711facfSdinak 				 * into ((X509 *)sk_value((ca_certs), (i))).
1617711facfSdinak 				 * Lint is complaining about the embedded
1627711facfSdinak 				 * casting, and to fix it, you need to fix
1637711facfSdinak 				 * openssl header files.
1647711facfSdinak 				 */
1657711facfSdinak 				/* LINTED E_BAD_PTR_CAST_ALIGN */
1667711facfSdinak 				ca = sk_X509_value(ca_certs, i);
1677711facfSdinak 
1687711facfSdinak 				/* Convert CA cert to PKCS#12 bag. */
1697711facfSdinak 				cryptodebug("adding CA certificate #%d "
1707711facfSdinak 				    "to PKCS#12 safebag", i+1);
1717711facfSdinak 				bag = PKCS12_x5092certbag(ca);
1727711facfSdinak 				if (bag == NULL) {
1737711facfSdinak 					cryptoerror(LOG_STDERR, gettext(
1747711facfSdinak 					    "Unable to convert CA certificate "
1757711facfSdinak 					    "#%d to PKCS#12 bag."), i+1);
1767711facfSdinak 					/* Cleanup the safebag. */
1777711facfSdinak 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
1787711facfSdinak 					    PKCS12_SAFEBAG_free);
1797711facfSdinak 					(*failures)++;
1807711facfSdinak 					return (-1);
1817711facfSdinak 				}
1827711facfSdinak 
1837711facfSdinak 				/* Note CA certs do not have friendly name. */
1847711facfSdinak 
1857711facfSdinak 				/* Pile it onto the bag_stack. */
1867711facfSdinak 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
1877711facfSdinak 					cryptodebug("error not caught");
1887711facfSdinak 
1897711facfSdinak 				n_writes++;
1907711facfSdinak 			}
1917711facfSdinak 		}
1927711facfSdinak 
1937711facfSdinak 		/* Turn bag_stack of certs into encrypted authsafe. */
1947711facfSdinak 		cryptodebug("encrypt certificate PKCS#12 bag into "
1957711facfSdinak 		    "PKCS#7 authsafe");
1967711facfSdinak 		cert_authsafe = PKCS12_pack_p7encdata(
1977711facfSdinak 		    NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL,
1987711facfSdinak 		    0, PKCS12_DEFAULT_ITER, bag_stack);
1997711facfSdinak 
2007711facfSdinak 		/* Clear away this bag_stack, we're done with it. */
2017711facfSdinak 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
2027711facfSdinak 		bag_stack = NULL;
2037711facfSdinak 
2047711facfSdinak 		if (cert_authsafe == NULL) {
2057711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
2067711facfSdinak 			    "Unable to PKCS#7-encrypt certificate bag."));
2077711facfSdinak 			(*failures)++;
2087711facfSdinak 			return (-1);
2097711facfSdinak 		}
2107711facfSdinak 	}
2117711facfSdinak 
2127711facfSdinak 	/*
2137711facfSdinak 	 * Section 2:
2147711facfSdinak 	 *
2157711facfSdinak 	 * The second PKCS#12 container (safebag) will hold the private key
2167711facfSdinak 	 * that goes with the certificates above.  The results of this section
2177711facfSdinak 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
2187711facfSdinak 	 * private key, there is no point in creating the "safebag" or the
2197711facfSdinak 	 * "authsafe" so we go to the next section.
2207711facfSdinak 	 */
2217711facfSdinak 	if (priv_key != NULL) {
2227711facfSdinak 		/* Make a PKCS#8 shrouded key bag. */
2237711facfSdinak 		cryptodebug("create PKCS#8 shrouded key out of private key");
2247711facfSdinak 		p8 = EVP_PKEY2PKCS8(priv_key);
2257711facfSdinak 		if (p8 == NULL) {
2267711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
2277711facfSdinak 			    "Unable to create PKCS#8 shrouded key for "
2287711facfSdinak 			    "private key."));
2297711facfSdinak 			(*failures)++;
2307711facfSdinak 			return (-1);
2317711facfSdinak 		}
2327711facfSdinak 
2337711facfSdinak 		/* Put the shrouded key into a PKCS#12 bag. */
2347711facfSdinak 		cryptodebug("convert shrouded key to PKCS#12 bag");
2357711facfSdinak 		bag = PKCS12_MAKE_SHKEYBAG(
2367711facfSdinak 		    NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin,
2377711facfSdinak 		    -1, NULL, 0, PKCS12_DEFAULT_ITER, p8);
2387711facfSdinak 
2397711facfSdinak 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
2407711facfSdinak 		PKCS8_PRIV_KEY_INFO_free(p8);
2417711facfSdinak 		p8 = NULL;
2427711facfSdinak 
2437711facfSdinak 		if (bag == NULL) {
2447711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
2457711facfSdinak 			    "Unable to convert private key to PKCS#12 bag."));
2467711facfSdinak 			(*failures)++;
2477711facfSdinak 			return (-1);
2487711facfSdinak 		}
2497711facfSdinak 
2507711facfSdinak 		/* Add the key id to the certificate bag. */
2517711facfSdinak 		cryptodebug("add key id to PKCS#12 safebag");
2527711facfSdinak 		if (!PKCS12_add_localkeyid(bag, id, id_len))
2537711facfSdinak 			cryptodebug("error not caught");
2547711facfSdinak 
2557711facfSdinak 		/* Add the cert friendly name to the private key bag. */
2567711facfSdinak 		if (lab != NULL) {
2577711facfSdinak 			cryptodebug("label PKCS#12 safebag with friendly name");
2587711facfSdinak 			if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len))
2597711facfSdinak 				cryptodebug("error not caught");
2607711facfSdinak 		}
2617711facfSdinak 
2627711facfSdinak 		/* Start a PKCS#12 safebag container for the private key. */
2637711facfSdinak 		cryptodebug("creating private key PKCS#12 safebag");
2647711facfSdinak 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
2657711facfSdinak 		if (bag_stack == NULL) {
2667711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
2677711facfSdinak 			    "Unable to create PKCS#12 private key bag."));
2687711facfSdinak 			(*failures)++;
2697711facfSdinak 			return (-1);
2707711facfSdinak 		}
2717711facfSdinak 
2727711facfSdinak 		/* Pile on the private key on the bag_stack. */
2737711facfSdinak 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
2747711facfSdinak 			cryptodebug("error not caught");
2757711facfSdinak 
2767711facfSdinak 		/* Turn bag_stack with private key into unencrypted authsafe. */
2777711facfSdinak 		cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe");
2787711facfSdinak 		key_authsafe = PKCS12_pack_p7data(bag_stack);
2797711facfSdinak 
2807711facfSdinak 		/* Clear away this bag_stack, we're done with it. */
2817711facfSdinak 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
2827711facfSdinak 		bag_stack = NULL;
2837711facfSdinak 
2847711facfSdinak 		if (key_authsafe == NULL) {
2857711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
2867711facfSdinak 			    "Unable to PKCS#7-convert private key bag."));
2877711facfSdinak 			(*failures)++;
2887711facfSdinak 			return (-1);
2897711facfSdinak 		}
2907711facfSdinak 
2917711facfSdinak 		n_writes++;
2927711facfSdinak 	}
2937711facfSdinak 
2947711facfSdinak 	/*
2957711facfSdinak 	 * Section 3:
2967711facfSdinak 	 *
2977711facfSdinak 	 * This is where the two PKCS#7 containers, one for the certificates
2987711facfSdinak 	 * and one for the private key, are put together into a PKCS#12
2997711facfSdinak 	 * element.  This final PKCS#12 element is written to the export file.
3007711facfSdinak 	 */
3017711facfSdinak 	/* Start a PKCS#7 stack. */
3027711facfSdinak 	cryptodebug("create PKCS#7 authsafe for private key and certificates");
3037711facfSdinak 	authsafe_stack = sk_PKCS7_new_null();
3047711facfSdinak 	if (authsafe_stack == NULL) {
3057711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
3067711facfSdinak 		    "Unable to create PKCS#7 container for private key "
3077711facfSdinak 		    "and certificates."));
3087711facfSdinak 		(*failures)++;
3097711facfSdinak 		return (-1);
3107711facfSdinak 	}
3117711facfSdinak 
3127711facfSdinak 	/* Put certificates and private key into PKCS#7 stack. */
3137711facfSdinak 	if (key_authsafe != NULL) {
3147711facfSdinak 		cryptodebug("put private key authsafe into PKCS#7 container");
3157711facfSdinak 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe))
3167711facfSdinak 			cryptodebug("error not caught");
3177711facfSdinak 	}
3187711facfSdinak 	if (cert_authsafe != NULL) {
3197711facfSdinak 		cryptodebug("put certificate authsafe into PKCS#7 container");
3207711facfSdinak 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe))
3217711facfSdinak 			cryptodebug("error not caught");
3227711facfSdinak 	}
3237711facfSdinak 
3247711facfSdinak 	/* Create PKCS#12 element out of PKCS#7 stack. */
3257711facfSdinak 	cryptodebug("create PKCS#12 element for export file");
3267711facfSdinak 	p12_elem = PKCS12_init(NID_pkcs7_data);
3277711facfSdinak 	if (p12_elem == NULL) {
3287711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
3297711facfSdinak 		    "Unable to create PKCS#12 element for export file."));
3307711facfSdinak 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3317711facfSdinak 		(*failures)++;
3327711facfSdinak 		return (-1);
3337711facfSdinak 	}
3347711facfSdinak 
3357711facfSdinak 	/* Put the PKCS#7 stack into the PKCS#12 element. */
3367711facfSdinak 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack))
3377711facfSdinak 		cryptodebug("error not caught");
3387711facfSdinak 
3397711facfSdinak 	/* Clear away the PKCS#7 stack, we're done with it. */
3407711facfSdinak 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
3417711facfSdinak 	authsafe_stack = NULL;
3427711facfSdinak 
3437711facfSdinak 	/* Set the integrity MAC on the PKCS#12 element. */
3447711facfSdinak 	cryptodebug("setting MAC for PKCS#12 element");
3457711facfSdinak 	if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0,
3467711facfSdinak 	    PKCS12_DEFAULT_ITER, NULL))
3477711facfSdinak 		cryptodebug("error not caught");
3487711facfSdinak 
3497711facfSdinak 	/* Write the PKCS#12 element to the export file. */
3507711facfSdinak 	cryptodebug("writing PKCS#12 element to export file");
3517711facfSdinak 	if (!i2d_PKCS12_bio(fbio, p12_elem))
3527711facfSdinak 		cryptodebug("error not caught");
3537711facfSdinak 
3547711facfSdinak 	(*successes) += n_writes;
3557711facfSdinak 
3567711facfSdinak 	/* Clear away the PKCS#12 element. */
3577711facfSdinak 	PKCS12_free(p12_elem);
3587711facfSdinak 	return (0);
3597711facfSdinak }
3607711facfSdinak 
3617711facfSdinak /*
3627711facfSdinak  * Get token objects: private key, its cert, and its cert chain.
3637711facfSdinak  */
3647711facfSdinak static CK_RV
3657711facfSdinak get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
3667711facfSdinak 	CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain,
3677711facfSdinak 	CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len)
3687711facfSdinak {
3697711facfSdinak 	CK_RV			rv = CKR_OK;
3707711facfSdinak 	CK_ATTRIBUTE		keyid_attr[1] = {
3717711facfSdinak 		{ CKA_ID, NULL, 0 }
3727711facfSdinak 	    };
3737711facfSdinak 	static CK_OBJECT_CLASS	class = CKO_CERTIFICATE;
3747711facfSdinak 	static CK_CERTIFICATE_TYPE	certtype = CKC_X_509;
3757711facfSdinak 	CK_ATTRIBUTE		cert_attr[4] = {
3767711facfSdinak 		{ CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) },
3777711facfSdinak 		{ CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
3787711facfSdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
3797711facfSdinak 		{ CKA_ID, NULL, 0 }
3807711facfSdinak 	    };
3817711facfSdinak 	CK_ULONG	num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE);
3827711facfSdinak 	CK_OBJECT_HANDLE	cert = ~0UL;
3837711facfSdinak 	CK_ULONG		num = 0;
3847711facfSdinak 
3857711facfSdinak 	cryptodebug("inside get_token_objs");
3867711facfSdinak 
3877711facfSdinak 	/* Get the size of the object's CKA_ID field first. */
3887711facfSdinak 	cryptodebug("getting CKA_ID size for object 0x%x", obj);
3897711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
3907711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get size of object"
3917711facfSdinak 		    " key id (%s)."), pkcs11_strerror(rv));
3927711facfSdinak 		return (rv);
3937711facfSdinak 	}
3947711facfSdinak 
3957711facfSdinak 	/* Allocate the space needed for the key id. */
3967711facfSdinak 	if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) {
3977711facfSdinak 		cryptoerror(LOG_STDERR, "%s.", strerror(errno));
3987711facfSdinak 		return (CKR_HOST_MEMORY);
3997711facfSdinak 	}
4007711facfSdinak 
4017711facfSdinak 	/* Get the CKA_ID field to match obj with its cert. */
4027711facfSdinak 	cryptodebug("getting CKA_ID attribute for object 0x%x", obj);
4037711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
4047711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get object "
4057711facfSdinak 		    "key id (%s)."), pkcs11_strerror(rv));
4067711facfSdinak 		free(keyid_attr[0].pValue);
4077711facfSdinak 		return (rv);
4087711facfSdinak 	}
4097711facfSdinak 
4107711facfSdinak 	/* Now try to find any certs that have the same id. */
4117711facfSdinak 	cryptodebug("searching for certificates with same CKA_ID");
4127711facfSdinak 	cert_attr[3].pValue = keyid_attr[0].pValue;
4137711facfSdinak 	cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen;
4147711facfSdinak 	if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) {
4157711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Unable to initialize "
4167711facfSdinak 		    "certificate search (%s)."), pkcs11_strerror(rv));
4177711facfSdinak 		free(keyid_attr[0].pValue);
4187711facfSdinak 		return (rv);
4197711facfSdinak 	}
4207711facfSdinak 
4217711facfSdinak 	/* Find the first cert that matches the key id. */
4227711facfSdinak 	if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) {
4237711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Certificate search failed "
4247711facfSdinak 		    "(%s)."), pkcs11_strerror(rv));
4257711facfSdinak 		free(keyid_attr[0].pValue);
4267711facfSdinak 		return (rv);
4277711facfSdinak 	}
4287711facfSdinak 
4297711facfSdinak 	(void) C_FindObjectsFinal(sess);
4307711facfSdinak 
4317711facfSdinak 	*id = keyid_attr[0].pValue;
4327711facfSdinak 	*id_len = keyid_attr[0].ulValueLen;
4337711facfSdinak 
4347711facfSdinak 	*mate = (num == 1) ? cert : ~0UL;
4357711facfSdinak 
4367711facfSdinak 	/* We currently do not find all the certs in the chain. */
4377711facfSdinak 	*chain_len = 0;
4387711facfSdinak 	*chain = NULL;
4397711facfSdinak 
4407711facfSdinak 	return (CKR_OK);
4417711facfSdinak }
4427711facfSdinak 
4437711facfSdinak /*
4447711facfSdinak  * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM.
4457711facfSdinak  * "to" should be the address of a ptr init'ed to NULL to
4467711facfSdinak  * receive the BIGNUM, e.g.,
4477711facfSdinak  *	biginteger_t	from;
4487711facfSdinak  * 	BIGNUM	*foo = NULL;
4497711facfSdinak  *	cvt_bigint2bn(&from, &foo);
4507711facfSdinak  */
4517711facfSdinak static int
4527711facfSdinak cvt_bigint2bn(biginteger_t *from, BIGNUM **to)
4537711facfSdinak {
4547711facfSdinak 	BIGNUM	*temp = NULL;
4557711facfSdinak 
4567711facfSdinak 	cryptodebug("inside cvt_bigint2bn");
4577711facfSdinak 
4587711facfSdinak 	if (from == NULL || to == NULL)
4597711facfSdinak 		return (-1);
4607711facfSdinak 
4617711facfSdinak 	cryptodebug("calling BN_bin2bn");
4627711facfSdinak 	if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) ==
4637711facfSdinak 	    NULL)
4647711facfSdinak 		return (-1);
4657711facfSdinak 
4667711facfSdinak 	*to = temp;
4677711facfSdinak 	return (0);
4687711facfSdinak }
4697711facfSdinak 
4707711facfSdinak /*
4717711facfSdinak  * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure.
4727711facfSdinak  */
4737711facfSdinak static CK_RV
4747711facfSdinak cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
4757711facfSdinak {
4767711facfSdinak 	CK_RV		rv = CKR_OK;
4777711facfSdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
4787711facfSdinak 	RSA		*rsa = NULL;		/* OpenSSL representation */
4797711facfSdinak 	biginteger_t	mod = { NULL, 0 };	/* required */
4807711facfSdinak 	biginteger_t	pubexp = { NULL, 0 };	/* required */
4817711facfSdinak 	biginteger_t	priexp = { NULL, 0 };	/* optional */
4827711facfSdinak 	biginteger_t	prime1 = { NULL, 0 };	/* optional */
4837711facfSdinak 	biginteger_t	prime2 = { NULL, 0 };	/* optional */
4847711facfSdinak 	biginteger_t	exp1 = { NULL, 0 };	/* optional */
4857711facfSdinak 	biginteger_t	exp2 = { NULL, 0 };	/* optional */
4867711facfSdinak 	biginteger_t	coef = { NULL, 0 };	/* optional */
4877711facfSdinak 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
4887711facfSdinak 		{ CKA_MODULUS, NULL, 0 },
4897711facfSdinak 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
4907711facfSdinak 		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
4917711facfSdinak 		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
4927711facfSdinak 		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
4937711facfSdinak 		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
4947711facfSdinak 		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
4957711facfSdinak 		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
4967711facfSdinak 	    };
4977711facfSdinak 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
4987711facfSdinak 	int		i;
4997711facfSdinak 
5007711facfSdinak 	cryptodebug("inside cvt_rsa2evp_pkey");
5017711facfSdinak 
5027711facfSdinak 	cryptodebug("calling RSA_new");
5037711facfSdinak 	if ((rsa = RSA_new()) == NULL) {
5047711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
5057711facfSdinak 		    "Unable to allocate internal RSA structure."));
5067711facfSdinak 		return (CKR_HOST_MEMORY);
5077711facfSdinak 	}
5087711facfSdinak 
5097711facfSdinak 	/* Get the sizes of the attributes we need. */
5107711facfSdinak 	cryptodebug("calling C_GetAttributeValue for size info");
5117711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
5127711facfSdinak 	    CKR_OK) {
5137711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
5147711facfSdinak 		    "Unable to get RSA private key attribute sizes (%s)."),
5157711facfSdinak 		    pkcs11_strerror(rv));
5167711facfSdinak 		return (rv);
5177711facfSdinak 	}
5187711facfSdinak 
5197711facfSdinak 	/* Allocate memory for each attribute. */
5207711facfSdinak 	for (i = 0; i < count; i++) {
5217711facfSdinak 		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
5227711facfSdinak 		    rsa_pri_attrs[i].ulValueLen == 0) {
5237711facfSdinak 			cryptodebug("cvt_rsa2evp_pkey: *** should not happen");
5247711facfSdinak 			rsa_pri_attrs[i].ulValueLen = 0;
5257711facfSdinak 			continue;
5267711facfSdinak 		}
5277711facfSdinak 		if ((rsa_pri_attrs[i].pValue =
5287711facfSdinak 		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
5297711facfSdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
5307711facfSdinak 			return (CKR_HOST_MEMORY);
5317711facfSdinak 		}
5327711facfSdinak 	}
5337711facfSdinak 
5347711facfSdinak 	/* Now really get the attributes. */
5357711facfSdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
5367711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
5377711facfSdinak 	    CKR_OK) {
5387711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
5397711facfSdinak 		    "Unable to get RSA private key attributes (%s)."),
5407711facfSdinak 		    pkcs11_strerror(rv));
5417711facfSdinak 		return (rv);
5427711facfSdinak 	}
5437711facfSdinak 
5447711facfSdinak 	/*
5457711facfSdinak 	 * Fill in all the temp variables.  Modulus and public exponent
5467711facfSdinak 	 * are required.  The rest are optional.
5477711facfSdinak 	 */
5487711facfSdinak 	i = 0;
5497711facfSdinak 	copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod);
5507711facfSdinak 	copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp);
5517711facfSdinak 
5527711facfSdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
5537711facfSdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
5547711facfSdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp);
5557711facfSdinak 	i++;
5567711facfSdinak 
5577711facfSdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
5587711facfSdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
5597711facfSdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1);
5607711facfSdinak 	i++;
5617711facfSdinak 
5627711facfSdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
5637711facfSdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
5647711facfSdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2);
5657711facfSdinak 	i++;
5667711facfSdinak 
5677711facfSdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
5687711facfSdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
5697711facfSdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1);
5707711facfSdinak 	i++;
5717711facfSdinak 
5727711facfSdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
5737711facfSdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
5747711facfSdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2);
5757711facfSdinak 	i++;
5767711facfSdinak 
5777711facfSdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
5787711facfSdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
5797711facfSdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef);
5807711facfSdinak 	i++;
5817711facfSdinak 
5827711facfSdinak 	/* Start the conversion to internal OpenSSL RSA structure. */
5837711facfSdinak 
5847711facfSdinak 	/* Modulus n */
5857711facfSdinak 	if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) {
5867711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
5877711facfSdinak 		    "Unable to convert RSA private key modulus."));
5887711facfSdinak 		return (CKR_GENERAL_ERROR);
5897711facfSdinak 	}
5907711facfSdinak 
5917711facfSdinak 	/* Public exponent e */
5927711facfSdinak 	if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) {
5937711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
5947711facfSdinak 		    "Unable to convert RSA private key public exponent."));
5957711facfSdinak 		return (CKR_GENERAL_ERROR);
5967711facfSdinak 	}
5977711facfSdinak 
5987711facfSdinak 	/* Private exponent e */
5997711facfSdinak 	if (priexp.big_value != NULL) {
6007711facfSdinak 		if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) {
6017711facfSdinak 			cryptoerror(LOG_STDERR, gettext("Unable to convert "
6027711facfSdinak 			    "RSA private key private exponent."));
6037711facfSdinak 			return (CKR_GENERAL_ERROR);
6047711facfSdinak 		}
6057711facfSdinak 	} else
6067711facfSdinak 		cryptodebug("no RSA private key private exponent");
6077711facfSdinak 
6087711facfSdinak 	/* Prime p */
6097711facfSdinak 	if (prime1.big_value != NULL) {
6107711facfSdinak 		if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) {
6117711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
6127711facfSdinak 			    "Unable to convert RSA private key prime 1."));
6137711facfSdinak 			return (CKR_GENERAL_ERROR);
6147711facfSdinak 		}
6157711facfSdinak 	} else
6167711facfSdinak 		cryptodebug("no RSA private key prime 1");
6177711facfSdinak 
6187711facfSdinak 	/* Prime q */
6197711facfSdinak 	if (prime2.big_value != NULL) {
6207711facfSdinak 		if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) {
6217711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
6227711facfSdinak 			    "Unable to convert RSA private key prime 2."));
6237711facfSdinak 			return (CKR_GENERAL_ERROR);
6247711facfSdinak 		}
6257711facfSdinak 	} else
6267711facfSdinak 		cryptodebug("no RSA private key prime 2");
6277711facfSdinak 
6287711facfSdinak 	/* Private exponent d modulo p-1 */
6297711facfSdinak 	if (exp1.big_value != NULL) {
6307711facfSdinak 		if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) {
6317711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
6327711facfSdinak 			    "Unable to convert RSA private key exponent 1."));
6337711facfSdinak 			return (CKR_GENERAL_ERROR);
6347711facfSdinak 		}
6357711facfSdinak 	} else
6367711facfSdinak 		cryptodebug("no RSA private key exponent 1");
6377711facfSdinak 
6387711facfSdinak 	/* Private exponent d modulo q-1 */
6397711facfSdinak 	if (exp2.big_value != NULL) {
6407711facfSdinak 		if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) {
6417711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
6427711facfSdinak 			    "Unable to convert RSA private key exponent 2."));
6437711facfSdinak 			return (CKR_GENERAL_ERROR);
6447711facfSdinak 		}
6457711facfSdinak 	} else
6467711facfSdinak 		cryptodebug("no RSA private key exponent 2");
6477711facfSdinak 
6487711facfSdinak 	/* CRT coefficient q-inverse mod p */
6497711facfSdinak 	if (coef.big_value != NULL) {
6507711facfSdinak 		if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) {
6517711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
6527711facfSdinak 			    "Unable to convert RSA private key coefficient."));
6537711facfSdinak 			return (CKR_GENERAL_ERROR);
6547711facfSdinak 		}
6557711facfSdinak 	} else
6567711facfSdinak 		cryptodebug("no RSA private key coefficient");
6577711facfSdinak 
6587711facfSdinak 	/* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */
6597711facfSdinak 	cryptodebug("calling EVP_PKEY_new");
6607711facfSdinak 	if ((key = EVP_PKEY_new()) == NULL) {
6617711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
6627711facfSdinak 		    "Unable to allocate internal EVP_PKEY structure."));
6637711facfSdinak 		return (CKR_HOST_MEMORY);
6647711facfSdinak 	}
6657711facfSdinak 
6667711facfSdinak 	/* Put the RSA struct into the EVP_PKEY struct and return it. */
6677711facfSdinak 	cryptodebug("calling EVP_PKEY_set1_RSA");
6687711facfSdinak 	(void) EVP_PKEY_set1_RSA(key, rsa);
6697711facfSdinak 
6707711facfSdinak 	*pk = key;
6717711facfSdinak 	return (CKR_OK);
6727711facfSdinak }
6737711facfSdinak 
6747711facfSdinak /*
6757711facfSdinak  * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure.
6767711facfSdinak  */
6777711facfSdinak static CK_RV
6787711facfSdinak cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
6797711facfSdinak {
6807711facfSdinak 	CK_RV		rv = CKR_OK;
6817711facfSdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
6827711facfSdinak 	DSA		*dsa = NULL;		/* OpenSSL representation */
6837711facfSdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
6847711facfSdinak 	biginteger_t	subprime = { NULL, 0 };	/* required */
6857711facfSdinak 	biginteger_t	base = { NULL, 0 };	/* required */
6867711facfSdinak 	biginteger_t	value = { NULL, 0 };	/* required */
6877711facfSdinak 	CK_ATTRIBUTE	dsa_pri_attrs[4] = {
6887711facfSdinak 		{ CKA_PRIME, NULL, 0 },
6897711facfSdinak 		{ CKA_SUBPRIME, NULL, 0 },
6907711facfSdinak 		{ CKA_BASE, NULL, 0 },
6917711facfSdinak 		{ CKA_VALUE, NULL, 0 }
6927711facfSdinak 	    };
6937711facfSdinak 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
6947711facfSdinak 	int		i;
6957711facfSdinak 
6967711facfSdinak 	cryptodebug("inside cvt_dsa2evp_pkey");
6977711facfSdinak 
6987711facfSdinak 	cryptodebug("calling DSA_new");
6997711facfSdinak 	if ((dsa = DSA_new()) == NULL) {
7007711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7017711facfSdinak 		    "Unable to allocate internal DSA structure."));
7027711facfSdinak 		return (CKR_HOST_MEMORY);
7037711facfSdinak 	}
7047711facfSdinak 
7057711facfSdinak 	/* Get the sizes of the attributes we need. */
7067711facfSdinak 	cryptodebug("calling C_GetAttributeValue for size info");
7077711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
7087711facfSdinak 	    CKR_OK) {
7097711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7107711facfSdinak 		    "Unable to get DSA private key object attributes (%s)."),
7117711facfSdinak 		    pkcs11_strerror(rv));
7127711facfSdinak 		return (rv);
7137711facfSdinak 	}
7147711facfSdinak 
7157711facfSdinak 	/* Allocate memory for each attribute. */
7167711facfSdinak 	for (i = 0; i < count; i++) {
7177711facfSdinak 		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
7187711facfSdinak 		    dsa_pri_attrs[i].ulValueLen == 0) {
7197711facfSdinak 			cryptodebug("cvt_dsa2evp_pkey:  *** should not happen");
7207711facfSdinak 			dsa_pri_attrs[i].ulValueLen = 0;
7217711facfSdinak 			continue;
7227711facfSdinak 		}
7237711facfSdinak 		if ((dsa_pri_attrs[i].pValue =
7247711facfSdinak 		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
7257711facfSdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
7267711facfSdinak 			return (CKR_HOST_MEMORY);
7277711facfSdinak 		}
7287711facfSdinak 	}
7297711facfSdinak 
7307711facfSdinak 	/* Now really get the attributes. */
7317711facfSdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
7327711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
7337711facfSdinak 	    CKR_OK) {
7347711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7357711facfSdinak 		    "Unable to get DSA private key attributes (%s)."),
7367711facfSdinak 		    pkcs11_strerror(rv));
7377711facfSdinak 		return (rv);
7387711facfSdinak 	}
7397711facfSdinak 
7407711facfSdinak 	/* Fill in all the temp variables.  They are all required. */
7417711facfSdinak 	i = 0;
7427711facfSdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime);
7437711facfSdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime);
7447711facfSdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base);
7457711facfSdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value);
7467711facfSdinak 
7477711facfSdinak 	/* Start the conversion to internal OpenSSL DSA structure. */
7487711facfSdinak 
7497711facfSdinak 	/* Prime p */
7507711facfSdinak 	if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) {
7517711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7527711facfSdinak 		    "Unable to convert DSA private key prime."));
7537711facfSdinak 		return (CKR_GENERAL_ERROR);
7547711facfSdinak 	}
7557711facfSdinak 
7567711facfSdinak 	/* Subprime q */
7577711facfSdinak 	if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) {
7587711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7597711facfSdinak 		    "Unable to convert DSA private key subprime."));
7607711facfSdinak 		return (CKR_GENERAL_ERROR);
7617711facfSdinak 	}
7627711facfSdinak 
7637711facfSdinak 	/* Base g */
7647711facfSdinak 	if (cvt_bigint2bn(&base, &(dsa->g)) < 0) {
7657711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7667711facfSdinak 		    "Unable to convert DSA private key base."));
7677711facfSdinak 		return (CKR_GENERAL_ERROR);
7687711facfSdinak 	}
7697711facfSdinak 
7707711facfSdinak 	/* Private key x */
7717711facfSdinak 	if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) {
7727711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7737711facfSdinak 		    "Unable to convert DSA private key value."));
7747711facfSdinak 		return (CKR_GENERAL_ERROR);
7757711facfSdinak 	}
7767711facfSdinak 
7777711facfSdinak 	/* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */
7787711facfSdinak 	cryptodebug("calling EVP_PKEY_new");
7797711facfSdinak 	if ((key = EVP_PKEY_new()) == NULL) {
7807711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
7817711facfSdinak 		    "Unable to allocate internal EVP_PKEY structure."));
7827711facfSdinak 		return (CKR_HOST_MEMORY);
7837711facfSdinak 	}
7847711facfSdinak 
7857711facfSdinak 	/* Put the DSA struct into the EVP_PKEY struct and return it. */
7867711facfSdinak 	cryptodebug("calling EVP_PKEY_set1_DSA");
7877711facfSdinak 	(void) EVP_PKEY_set1_DSA(key, dsa);
7887711facfSdinak 
7897711facfSdinak 	*pk = key;
7907711facfSdinak 	return (CKR_OK);
7917711facfSdinak }
7927711facfSdinak 
7937711facfSdinak /*
7947711facfSdinak  * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure.
7957711facfSdinak  */
7967711facfSdinak static CK_RV
7977711facfSdinak cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
7987711facfSdinak {
7997711facfSdinak 	CK_RV		rv = CKR_OK;
8007711facfSdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
8017711facfSdinak 	DH		*dh = NULL;		/* OpenSSL representation */
8027711facfSdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
8037711facfSdinak 	biginteger_t	base = { NULL, 0 };	/* required */
8047711facfSdinak 	biginteger_t	value = { NULL, 0 };	/* required */
8057711facfSdinak 	CK_ATTRIBUTE	dh_pri_attrs[3] = {
8067711facfSdinak 		{ CKA_PRIME, NULL, 0 },
8077711facfSdinak 		{ CKA_BASE, NULL, 0 },
8087711facfSdinak 		{ CKA_VALUE, NULL, 0 }
8097711facfSdinak 	    };
8107711facfSdinak 	CK_ULONG	count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
8117711facfSdinak 	int		i;
8127711facfSdinak 
8137711facfSdinak 	cryptodebug("inside cvt_dh2evp_pkey");
8147711facfSdinak 
8157711facfSdinak 	cryptodebug("calling DH_new");
8167711facfSdinak 	if ((dh = DH_new()) == NULL) {
8177711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8187711facfSdinak 		    "Unable to allocate internal DH structure."));
8197711facfSdinak 		return (CKR_HOST_MEMORY);
8207711facfSdinak 	}
8217711facfSdinak 
8227711facfSdinak 	/* Get the sizes of the attributes we need. */
8237711facfSdinak 	cryptodebug("calling C_GetAttributeValue for size info");
8247711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
8257711facfSdinak 	    CKR_OK) {
8267711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8277711facfSdinak 		    "Unable to get DH private key object attributes (%s)."),
8287711facfSdinak 		    pkcs11_strerror(rv));
8297711facfSdinak 		return (rv);
8307711facfSdinak 	}
8317711facfSdinak 
8327711facfSdinak 	/* Allocate memory for each attribute. */
8337711facfSdinak 	for (i = 0; i < count; i++) {
8347711facfSdinak 		if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
8357711facfSdinak 		    dh_pri_attrs[i].ulValueLen == 0) {
8367711facfSdinak 			cryptodebug("cvt_dh2evp_pkey: ***should not happen");
8377711facfSdinak 			dh_pri_attrs[i].ulValueLen = 0;
8387711facfSdinak 			continue;
8397711facfSdinak 		}
8407711facfSdinak 		if ((dh_pri_attrs[i].pValue =
8417711facfSdinak 		    malloc(dh_pri_attrs[i].ulValueLen)) == NULL) {
8427711facfSdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
8437711facfSdinak 			return (CKR_HOST_MEMORY);
8447711facfSdinak 		}
8457711facfSdinak 	}
8467711facfSdinak 
8477711facfSdinak 	/* Now really get the attributes. */
8487711facfSdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
8497711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
8507711facfSdinak 	    CKR_OK) {
8517711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8527711facfSdinak 		    "Unable to get DH private key attributes (%s)."),
8537711facfSdinak 		    pkcs11_strerror(rv));
8547711facfSdinak 		return (rv);
8557711facfSdinak 	}
8567711facfSdinak 
8577711facfSdinak 	/* Fill in all the temp variables.  They are all required. */
8587711facfSdinak 	i = 0;
8597711facfSdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime);
8607711facfSdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base);
8617711facfSdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value);
8627711facfSdinak 
8637711facfSdinak 	/* Start the conversion to internal OpenSSL DH structure. */
8647711facfSdinak 
8657711facfSdinak 	/* Prime p */
8667711facfSdinak 	if (cvt_bigint2bn(&prime, &(dh->p)) < 0) {
8677711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8687711facfSdinak 		    "Unable to convert DH private key prime."));
8697711facfSdinak 		return (CKR_GENERAL_ERROR);
8707711facfSdinak 	}
8717711facfSdinak 
8727711facfSdinak 	/* Base g */
8737711facfSdinak 	if (cvt_bigint2bn(&base, &(dh->g)) < 0) {
8747711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8757711facfSdinak 		    "Unable to convert DH private key base."));
8767711facfSdinak 		return (CKR_GENERAL_ERROR);
8777711facfSdinak 	}
8787711facfSdinak 
8797711facfSdinak 	/* Private value x */
8807711facfSdinak 	if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) {
8817711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8827711facfSdinak 		    "Unable to convert DH private key value."));
8837711facfSdinak 		return (CKR_GENERAL_ERROR);
8847711facfSdinak 	}
8857711facfSdinak 
8867711facfSdinak 	/* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */
8877711facfSdinak 	cryptodebug("calling EVP_PKEY_new");
8887711facfSdinak 	if ((key = EVP_PKEY_new()) == NULL) {
8897711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
8907711facfSdinak 		    "Unable to allocate internal EVP_PKEY structure."));
8917711facfSdinak 		return (CKR_HOST_MEMORY);
8927711facfSdinak 	}
8937711facfSdinak 
8947711facfSdinak 	/* Put the DH struct into the EVP_PKEY struct and return it. */
8957711facfSdinak 	cryptodebug("calling EVP_PKEY_set1_DH");
8967711facfSdinak 	(void) EVP_PKEY_set1_DH(key, dh);
8977711facfSdinak 
8987711facfSdinak 	*pk = key;
8997711facfSdinak 	return (CKR_OK);
9007711facfSdinak }
9017711facfSdinak 
9027711facfSdinak /*
9037711facfSdinak  * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure.
9047711facfSdinak  */
9057711facfSdinak static CK_RV
9067711facfSdinak cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
9077711facfSdinak {
9087711facfSdinak 	CK_RV			rv = CKR_OK;
9097711facfSdinak 	static CK_KEY_TYPE	keytype = 0;
9107711facfSdinak 	CK_ATTRIBUTE		keytype_attr[1] = {
9117711facfSdinak 		{ CKA_KEY_TYPE, &keytype, sizeof (keytype) }
9127711facfSdinak 	    };
9137711facfSdinak 
9147711facfSdinak 	cryptodebug("inside cvt_obj2evp_pkey");
9157711facfSdinak 
9167711facfSdinak 	/* Find out the key type to do the right conversion. */
9177711facfSdinak 	cryptodebug("calling C_GetAttributeValue");
9187711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) !=
9197711facfSdinak 	    CKR_OK) {
9207711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
9217711facfSdinak 		    "Unable to get token object key type (%s)."),
9227711facfSdinak 		    pkcs11_strerror(rv));
9237711facfSdinak 		return (rv);
9247711facfSdinak 	}
9257711facfSdinak 
9267711facfSdinak 	switch (keytype) {
9277711facfSdinak 	case CKK_RSA:
9287711facfSdinak 		cryptodebug("converting RSA key");
9297711facfSdinak 		return (cvt_rsa2evp_pkey(sess, obj, pk));
9307711facfSdinak 	case CKK_DSA:
9317711facfSdinak 		cryptodebug("converting DSA key");
9327711facfSdinak 		return (cvt_dsa2evp_pkey(sess, obj, pk));
9337711facfSdinak 	case CKK_DH:
9347711facfSdinak 		cryptodebug("converting DH key");
9357711facfSdinak 		return (cvt_dh2evp_pkey(sess, obj, pk));
9367711facfSdinak 	default:
9377711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
9387711facfSdinak 		    "Private key type 0x%02x conversion not supported."),
9397711facfSdinak 		    keytype);
9407711facfSdinak 		return (CKR_GENERAL_ERROR);
9417711facfSdinak 	}
9427711facfSdinak }
9437711facfSdinak 
9447711facfSdinak /*
9457711facfSdinak  * Convert PKCS#11 certificate object to OpenSSL X509 structure.
9467711facfSdinak  */
9477711facfSdinak static CK_RV
9487711facfSdinak cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c)
9497711facfSdinak {
9507711facfSdinak 	CK_RV			rv = CKR_OK;
9517711facfSdinak 	X509			*cert = NULL;	/* OpenSSL representation */
9527711facfSdinak 	X509			*temp_cert = NULL;
9537711facfSdinak 	CK_BYTE			*subject = NULL;
9547711facfSdinak 	CK_ULONG		subject_len = 0;
9557711facfSdinak 	CK_BYTE			*value = NULL;
9567711facfSdinak 	CK_ULONG		value_len = 0;
9577711facfSdinak 	CK_BYTE			*label = NULL;
9587711facfSdinak 	CK_ULONG		label_len = 0;
9597711facfSdinak 	CK_BYTE			*id = NULL;
9607711facfSdinak 	CK_ULONG		id_len = 0;
9617711facfSdinak 	CK_BYTE			*issuer = NULL;
9627711facfSdinak 	CK_ULONG		issuer_len = 0;
9637711facfSdinak 	CK_BYTE			*serial = NULL;
9647711facfSdinak 	CK_ULONG		serial_len = 0;
9657711facfSdinak 	CK_ATTRIBUTE		cert_attrs[6] = {
9667711facfSdinak 		{ CKA_SUBJECT, NULL, 0 },		/* required */
9677711facfSdinak 		{ CKA_VALUE, NULL, 0 },			/* required */
9687711facfSdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
9697711facfSdinak 		{ CKA_ID, NULL, 0 },			/* optional */
9707711facfSdinak 		{ CKA_ISSUER, NULL, 0 },		/* optional */
9717711facfSdinak 		{ CKA_SERIAL_NUMBER, NULL, 0 }		/* optional */
9727711facfSdinak 	    };
9737711facfSdinak 	CK_ULONG	count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
9747711facfSdinak 	int		i = 0;
9757711facfSdinak 	X509_NAME	*ssl_subject = NULL;
9767711facfSdinak 	X509_NAME	*ssl_issuer = NULL;
9777711facfSdinak 	ASN1_INTEGER	*ssl_serial = NULL;
9787711facfSdinak 
9797711facfSdinak 	cryptodebug("inside cvt_cert2x509");
9807711facfSdinak 
9817711facfSdinak 	cryptodebug("calling X509_new");
9827711facfSdinak 	if ((cert = X509_new()) == NULL) {
9837711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
9847711facfSdinak 		    "Unable to allocate internal X509 structure."));
9857711facfSdinak 		return (CKR_HOST_MEMORY);
9867711facfSdinak 	}
9877711facfSdinak 
9887711facfSdinak 	/* Get the sizes of the attributes we need. */
9897711facfSdinak 	cryptodebug("calling C_GetAttributeValue for size info");
9907711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
9917711facfSdinak 	    CKR_OK) {
9927711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
9937711facfSdinak 		    "Unable to get certificate attribute sizes (%s)."),
9947711facfSdinak 		    pkcs11_strerror(rv));
9957711facfSdinak 		return (rv);
9967711facfSdinak 	}
9977711facfSdinak 
9987711facfSdinak 	/* Allocate memory for each attribute. */
9997711facfSdinak 	for (i = 0; i < count; i++) {
10007711facfSdinak 		if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 ||
10017711facfSdinak 		    cert_attrs[i].ulValueLen == 0) {
10027711facfSdinak 			cryptodebug("cvt_cert2x509:  *** should not happen");
10037711facfSdinak 			cert_attrs[i].ulValueLen = 0;
10047711facfSdinak 			continue;
10057711facfSdinak 		}
10067711facfSdinak 		if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen))
10077711facfSdinak 		    == NULL) {
10087711facfSdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
10097711facfSdinak 			return (CKR_HOST_MEMORY);
10107711facfSdinak 		}
10117711facfSdinak 	}
10127711facfSdinak 
10137711facfSdinak 	/* Now really get the attributes. */
10147711facfSdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
10157711facfSdinak 	if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
10167711facfSdinak 	    CKR_OK) {
10177711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
10187711facfSdinak 		    "Unable to get certificate attributes (%s)."),
10197711facfSdinak 		    pkcs11_strerror(rv));
10207711facfSdinak 		return (rv);
10217711facfSdinak 	}
10227711facfSdinak 
10237711facfSdinak 	/*
10247711facfSdinak 	 * Fill in all the temp variables.  Subject and value are required.
10257711facfSdinak 	 * The rest are optional.
10267711facfSdinak 	 */
10277711facfSdinak 	i = 0;
10287711facfSdinak 	copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len);
10297711facfSdinak 	copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len);
10307711facfSdinak 
10317711facfSdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
10327711facfSdinak 	    cert_attrs[i].ulValueLen != 0)
10337711facfSdinak 		copy_attr_to_string(&(cert_attrs[i]), &label, &label_len);
10347711facfSdinak 	i++;
10357711facfSdinak 
10367711facfSdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
10377711facfSdinak 	    cert_attrs[i].ulValueLen != 0)
10387711facfSdinak 		copy_attr_to_string(&(cert_attrs[i]), &id, &id_len);
10397711facfSdinak 	i++;
10407711facfSdinak 
10417711facfSdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
10427711facfSdinak 	    cert_attrs[i].ulValueLen != 0)
10437711facfSdinak 		copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len);
10447711facfSdinak 	i++;
10457711facfSdinak 
10467711facfSdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
10477711facfSdinak 	    cert_attrs[i].ulValueLen != 0)
10487711facfSdinak 		copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len);
10497711facfSdinak 	i++;
10507711facfSdinak 
10517711facfSdinak 	/* Start the conversion to internal OpenSSL X509 structure. */
10527711facfSdinak 
10537711facfSdinak 	/* Subject name (required) */
10547711facfSdinak 	cryptodebug("calling d2i_X509_NAME for subject name");
10557711facfSdinak 	if ((ssl_subject = d2i_X509_NAME(NULL, &subject, subject_len)) ==
10567711facfSdinak 	    NULL) {
10577711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
10587711facfSdinak 		    "Unable to convert certificate subject name."));
10597711facfSdinak 		return (CKR_GENERAL_ERROR);
10607711facfSdinak 	}
10617711facfSdinak 	cryptodebug("calling X509_set_subject_name");
10627711facfSdinak 	if (!X509_set_subject_name(cert, ssl_subject)) {
10637711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
10647711facfSdinak 		    "Unable to pack certificate subject name entries."));
10657711facfSdinak 		return (CKR_GENERAL_ERROR);
10667711facfSdinak 	}
10677711facfSdinak 
10687711facfSdinak 	/* Label (optional) */
10697711facfSdinak 	cryptodebug("calling X509_alias_set1");
10707711facfSdinak 	if (!X509_alias_set1(cert, label, label_len))
10717711facfSdinak 		cryptodebug("error not caught");
10727711facfSdinak 
10737711facfSdinak 	/* Id (optional) */
10747711facfSdinak 	cryptodebug("calling X509_keyid_set1");
10757711facfSdinak 	if (!X509_keyid_set1(cert, id, id_len))
10767711facfSdinak 		cryptodebug("error not caught");
10777711facfSdinak 
10787711facfSdinak 	/* Issuer name (optional) */
10797711facfSdinak 	cryptodebug("calling d2i_X509_NAME for issuer name");
10807711facfSdinak 	if ((ssl_issuer = d2i_X509_NAME(NULL, &issuer, issuer_len)) == NULL) {
10817711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
10827711facfSdinak 		    "Unable to convert certificate issuer name."));
10837711facfSdinak 		return (CKR_GENERAL_ERROR);
10847711facfSdinak 	}
10857711facfSdinak 	cryptodebug("calling X509_set_issuer_name");
10867711facfSdinak 	if (!X509_set_issuer_name(cert, ssl_issuer)) {
10877711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
10887711facfSdinak 		    "Unable to pack certificate issuer name entries."));
10897711facfSdinak 		return (CKR_GENERAL_ERROR);
10907711facfSdinak 	}
10917711facfSdinak 
10927711facfSdinak 	/* Serial number (optional) */
10937711facfSdinak 	cryptodebug("calling c2i_ASN1_INTEGER for serial number");
10947711facfSdinak 	if ((ssl_serial = c2i_ASN1_INTEGER(NULL, &serial, serial_len)) ==
10957711facfSdinak 	    NULL) {
10967711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
10977711facfSdinak 		    "Unable to convert certificate serial number."));
10987711facfSdinak 		return (CKR_GENERAL_ERROR);
10997711facfSdinak 	}
11007711facfSdinak 	cryptodebug("calling X509_set_serialNumber");
11017711facfSdinak 	if (!X509_set_serialNumber(cert, ssl_serial))
11027711facfSdinak 		cryptodebug("error not caught");
11037711facfSdinak 
11047711facfSdinak 	/*
11057711facfSdinak 	 * Value (required)
11067711facfSdinak 	 *
11077711facfSdinak 	 * The rest of this code takes the CKA_VALUE attribute, converts
11087711facfSdinak 	 * it into a temp OpenSSL X509 structure and picks out the rest
11097711facfSdinak 	 * of the fields we need to convert it back into the current X509
11107711facfSdinak 	 * structure that will get exported.  The reason we don't just
11117711facfSdinak 	 * start with CKA_VALUE is because while the object was in the
11127711facfSdinak 	 * softtoken, it is possible that some of its attributes changed.
11137711facfSdinak 	 * Those changes would not appear in CKA_VALUE and would be lost
11147711facfSdinak 	 * if we started with CKA_VALUE that was saved originally.
11157711facfSdinak 	 */
11167711facfSdinak 	cryptodebug("calling d2i_X509 for cert value");
11177711facfSdinak 	if ((temp_cert = d2i_X509(NULL, &value, value_len)) == NULL) {
11187711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
11197711facfSdinak 		    "Unable to convert main certificate values."));
11207711facfSdinak 		return (CKR_GENERAL_ERROR);
11217711facfSdinak 	}
11227711facfSdinak 
11237711facfSdinak 	/* Transfer these values from temp_cert to cert. */
11247711facfSdinak 	cryptodebug("calling X509_set_version/X509_get_version");
11257711facfSdinak 	if (!X509_set_version(cert, X509_get_version(temp_cert)))
11267711facfSdinak 		cryptodebug("error not caught");
11277711facfSdinak 
11287711facfSdinak 	cryptodebug("calling X509_set_notBefore/X509_get_notBefore");
11297711facfSdinak 	if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert)))
11307711facfSdinak 		cryptodebug("error not caught");
11317711facfSdinak 
11327711facfSdinak 	cryptodebug("calling X509_set_notAfter/X509_get_notAfter");
11337711facfSdinak 	if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert)))
11347711facfSdinak 		cryptodebug("error not caught");
11357711facfSdinak 
11367711facfSdinak 	cryptodebug("calling X509_set_pubkey/X509_get_pubkey");
11377711facfSdinak 	if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert)))
11387711facfSdinak 		cryptodebug("error not caught");
11397711facfSdinak 
11407711facfSdinak 	/*
11417711facfSdinak 	 * These don't get transfered from temp_cert to cert.
11427711facfSdinak 	 * It -appears- that they may get regenerated as needed.
11437711facfSdinak 	 *
11447711facfSdinak 	 * cert->cert_info->signature = dup(temp_cert->cert_info->signature);
11457711facfSdinak 	 * cert->sig_alg = dup(temp_cert->sig_alg);
11467711facfSdinak 	 * cert->signature = dup(temp_cert->signature);
11477711facfSdinak 	 * cert->skid = dup(temp_cert->skid);
11487711facfSdinak 	 * cert->akid = dup(temp_cert->akid);
11497711facfSdinak 	 */
11507711facfSdinak 
11517711facfSdinak 	*c = cert;
11527711facfSdinak 	return (CKR_OK);
11537711facfSdinak }
11547711facfSdinak 
11557711facfSdinak static CK_RV
11567711facfSdinak convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
11577711facfSdinak 	CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len,
11587711facfSdinak 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
11597711facfSdinak {
11607711facfSdinak 	CK_RV		rv = CKR_OK;
11617711facfSdinak 	EVP_PKEY	*pk = NULL;
11627711facfSdinak 	X509		*c = NULL;
11637711facfSdinak 	X509		*one_ca = NULL;
11647711facfSdinak 	STACK_OF(X509)	*ch = NULL;
11657711facfSdinak 	int		i;
11667711facfSdinak 
11677711facfSdinak 	cryptodebug("inside convert_token_objs");
11687711facfSdinak 
11697711facfSdinak 	if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK)
11707711facfSdinak 		return (rv);
11717711facfSdinak 
11727711facfSdinak 	if (mate != ~0UL) {
11737711facfSdinak 		cryptodebug("converting cert corresponding to private key");
11747711facfSdinak 		if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK)
11757711facfSdinak 			return (rv);
11767711facfSdinak 	}
11777711facfSdinak 
11787711facfSdinak 	if (chain_len != 0) {
11797711facfSdinak 		cryptodebug("converting ca chain of %d certs corresponding "
11807711facfSdinak 		    "to private key", chain_len);
11817711facfSdinak 		ch = sk_X509_new_null();
11827711facfSdinak 		for (i = 0; i < chain_len; i++) {
11837711facfSdinak 			if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) !=
11847711facfSdinak 			    CKR_OK) {
11857711facfSdinak 				return (rv);
11867711facfSdinak 			}
11877711facfSdinak 			if (!sk_X509_push(ch, one_ca))
11887711facfSdinak 				cryptodebug("error not caught");
11897711facfSdinak 		}
11907711facfSdinak 	}
11917711facfSdinak 
11927711facfSdinak 	*priv_key = pk;
11937711facfSdinak 	*cert = (mate != ~0UL) ? c : NULL;
11947711facfSdinak 	*ca = (chain_len != 0) ? ch : NULL;
11957711facfSdinak 	return (CKR_OK);
11967711facfSdinak }
11977711facfSdinak 
11987711facfSdinak /*
11997711facfSdinak  * Export objects from token to PKCS#12 file.
12007711facfSdinak  */
12017711facfSdinak int
12027711facfSdinak pk_export(int argc, char *argv[])
12037711facfSdinak {
1204*49e21299Sdinak 	int		opt;
1205*49e21299Sdinak 	extern int	optind_av;
1206*49e21299Sdinak 	extern char	*optarg_av;
1207*49e21299Sdinak 	char		*token_spec = NULL;
12087711facfSdinak 	char		*token_name = NULL;
12097711facfSdinak 	char		*manuf_id = NULL;
12107711facfSdinak 	char		*serial_no = NULL;
12117711facfSdinak 	char		full_name[FULL_NAME_LEN];
12127711facfSdinak 	char		*filename = NULL;
12137711facfSdinak 	CK_SLOT_ID	slot_id;
12147711facfSdinak 	CK_FLAGS	pin_state;
12157711facfSdinak 	CK_UTF8CHAR_PTR	pin = NULL;
12167711facfSdinak 	CK_ULONG	pinlen = 0;
12177711facfSdinak 	CK_UTF8CHAR_PTR	pk12pin = NULL;
12187711facfSdinak 	CK_ULONG	pk12pinlen = 0;
12197711facfSdinak 	CK_SESSION_HANDLE	sess;
12207711facfSdinak 	BIO		*fbio = NULL;
12217711facfSdinak 	EVP_PKEY	*priv_key = NULL;
12227711facfSdinak 	X509		*cert = NULL;
12237711facfSdinak 	STACK_OF(X509)	*ca = NULL;
12247711facfSdinak 	CK_RV		rv = CKR_OK;
12257711facfSdinak 	CK_OBJECT_HANDLE	*objs = NULL;
12267711facfSdinak 	CK_ULONG	num_objs = 0;
12277711facfSdinak 	CK_OBJECT_HANDLE	mate = ~0UL;
12287711facfSdinak 	CK_OBJECT_HANDLE	*chain = NULL;
12297711facfSdinak 	CK_ULONG	chain_len;
12307711facfSdinak 	CK_BYTE		*id = NULL;
12317711facfSdinak 	CK_ULONG	id_len = 0;
12327711facfSdinak 	int		i = 0;
12337711facfSdinak 	int		good_ones = 0, bad_ones = 0;	/* running totals */
12347711facfSdinak 
12357711facfSdinak 	cryptodebug("inside pk_export");
12367711facfSdinak 
1237*49e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
1238*49e21299Sdinak 	while ((opt = getopt_av(argc, argv, "T:(token)o:(outfile)")) != EOF) {
1239*49e21299Sdinak 		switch (opt) {
1240*49e21299Sdinak 		case 'T':	/* token specifier */
1241*49e21299Sdinak 			if (token_spec)
1242*49e21299Sdinak 				return (PK_ERR_USAGE);
1243*49e21299Sdinak 			token_spec = optarg_av;
1244*49e21299Sdinak 			break;
1245*49e21299Sdinak 		case 'o':	/* output file name */
1246*49e21299Sdinak 			if (filename)
1247*49e21299Sdinak 				return (PK_ERR_USAGE);
1248*49e21299Sdinak 			filename = optarg_av;
1249*49e21299Sdinak 			break;
1250*49e21299Sdinak 		default:
1251*49e21299Sdinak 			return (PK_ERR_USAGE);
1252*49e21299Sdinak 			break;
1253*49e21299Sdinak 		}
1254*49e21299Sdinak 	}
12557711facfSdinak 
1256*49e21299Sdinak 	/* If nothing is specified, default is to use softtoken. */
1257*49e21299Sdinak 	if (token_spec == NULL) {
1258*49e21299Sdinak 		token_name = SOFT_TOKEN_LABEL;
1259*49e21299Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
1260*49e21299Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
1261*49e21299Sdinak 	} else {
1262*49e21299Sdinak 		/*
1263*49e21299Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
1264*49e21299Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
1265*49e21299Sdinak 		 */
1266*49e21299Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
1267*49e21299Sdinak 		    &serial_no) < 0)
1268*49e21299Sdinak 			return (PK_ERR_USAGE);
1269*49e21299Sdinak 	}
1270*49e21299Sdinak 
1271*49e21299Sdinak 	/* Filename arg is required. */
1272*49e21299Sdinak 	if (filename == NULL)
12737711facfSdinak 		return (PK_ERR_USAGE);
12747711facfSdinak 
1275*49e21299Sdinak 	/* No additional args allowed. */
1276*49e21299Sdinak 	argc -= optind_av;
1277*49e21299Sdinak 	argv += optind_av;
1278*49e21299Sdinak 	if (argc)
1279*49e21299Sdinak 		return (PK_ERR_USAGE);
12807711facfSdinak 	/* Done parsing command line options. */
12817711facfSdinak 
12827711facfSdinak 	/* Check if the file exists and might be overwritten. */
12837711facfSdinak 	if (access(filename, F_OK) == 0) {
12847711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, "
12857711facfSdinak 		    "will be overwritten."), filename);
12867711facfSdinak 		if (yesno(gettext("Continue with export? "),
12877711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
12887711facfSdinak 			return (0);
12897711facfSdinak 		}
12907711facfSdinak 	}
12917711facfSdinak 
12927711facfSdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
12937711facfSdinak 
12947711facfSdinak 	/* Find the slot with token. */
12957711facfSdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
12967711facfSdinak 	    &pin_state)) != CKR_OK) {
12977711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
12987711facfSdinak 		    "Unable to find token %s (%s)."), full_name,
12997711facfSdinak 		    pkcs11_strerror(rv));
13007711facfSdinak 		return (PK_ERR_PK11);
13017711facfSdinak 	}
13027711facfSdinak 
13037711facfSdinak 	/* Get the user's PIN. */
13047711facfSdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
13057711facfSdinak 	    &pinlen)) != CKR_OK) {
13067711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
13077711facfSdinak 		    "Unable to get token passphrase (%s)."),
13087711facfSdinak 		    pkcs11_strerror(rv));
13097711facfSdinak 		quick_finish(NULL);
13107711facfSdinak 		return (PK_ERR_PK11);
13117711facfSdinak 	}
13127711facfSdinak 
13137711facfSdinak 	/* Assume user must be logged in R/W to export objects from token. */
13147711facfSdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
13157711facfSdinak 	    CKR_OK) {
13167711facfSdinak 		cryptoerror(LOG_STDERR,
13177711facfSdinak 		    gettext("Unable to log into token (%s)."),
13187711facfSdinak 		    pkcs11_strerror(rv));
13197711facfSdinak 		quick_finish(sess);
13207711facfSdinak 		return (PK_ERR_PK11);
13217711facfSdinak 	}
13227711facfSdinak 
13237711facfSdinak 	/* Collect all private keys first. */
13247711facfSdinak 	if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL,
13257711facfSdinak 	    &objs, &num_objs)) != CKR_OK) {
13267711facfSdinak 		cryptoerror(LOG_STDERR, gettext(
13277711facfSdinak 		    "Unable to retrieve private key token objects (%s)."),
13287711facfSdinak 		    pkcs11_strerror(rv));
13297711facfSdinak 		quick_finish(sess);
13307711facfSdinak 		return (PK_ERR_PK11);
13317711facfSdinak 	}
13327711facfSdinak 
13337711facfSdinak 	/* Nothing to do? */
13347711facfSdinak 	if (num_objs == 0) {
13357711facfSdinak 		cryptoerror(LOG_STDERR, gettext("No objects found."));
13367711facfSdinak 		quick_finish(sess);
13377711facfSdinak 		return (0);
13387711facfSdinak 	}
13397711facfSdinak 
13407711facfSdinak 	/* Setup OpenSSL context. */
13417711facfSdinak 	PKTOOL_setup_openssl();
13427711facfSdinak 
13437711facfSdinak 	/* Create PKCS#12 file. */
13447711facfSdinak 	if ((create_pkcs12(filename, &fbio)) < 0) {
13457711facfSdinak 		cryptoerror(LOG_STDERR, gettext("No export file created."));
13467711facfSdinak 		quick_finish(sess);
13477711facfSdinak 		return (PK_ERR_SYSTEM);
13487711facfSdinak 	}
13497711facfSdinak 
13507711facfSdinak 	/* Get the PIN for the PKCS#12 export file. */
13517711facfSdinak 	if ((rv = get_pin(gettext("Create export file passphrase:"), gettext(
13527711facfSdinak 	    "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) !=
13537711facfSdinak 	    CKR_OK) {
13547711facfSdinak 		cryptoerror(LOG_STDERR,
13557711facfSdinak 		    gettext("Unable to get export file passphrase (%s)."),
13567711facfSdinak 		    pkcs11_strerror(rv));
13577711facfSdinak 		close_pkcs12(fbio);
13587711facfSdinak 		quick_finish(sess);
13597711facfSdinak 		return (PK_ERR_PK11);
13607711facfSdinak 	}
13617711facfSdinak 
13627711facfSdinak 	for (i = 0; i < num_objs; i++) {
13637711facfSdinak 		/* Get a private key and its certificate and CA chain. */
13647711facfSdinak 		if ((rv = get_token_objs(sess, objs[i], &mate, &chain,
13657711facfSdinak 		    &chain_len, &id, &id_len)) != CKR_OK) {
13667711facfSdinak 			/*
13677711facfSdinak 			 * Note this "rv" is either CKR_OK or !CKR_OK.  The
13687711facfSdinak 			 * real error codes/messages are handled inside
13697711facfSdinak 			 * read_token_objs().
13707711facfSdinak 			 */
13717711facfSdinak 			cryptoerror(LOG_STDERR,
13727711facfSdinak 			    gettext("Unable to get token objects."));
13737711facfSdinak 			free(id);
13747711facfSdinak 			close_pkcs12(fbio);
13757711facfSdinak 			quick_finish(sess);
13767711facfSdinak 			return (PK_ERR_PK11);
13777711facfSdinak 		}
13787711facfSdinak 
13797711facfSdinak 		/* Convert to OpenSSL equivalents. */
13807711facfSdinak 		if ((rv = convert_token_objs(sess, objs[i], mate, chain,
13817711facfSdinak 		    chain_len, &priv_key, &cert, &ca)) != CKR_OK) {
13827711facfSdinak 			/*
13837711facfSdinak 			 * Note this "rv" is either CKR_OK or !CKR_OK.  The
13847711facfSdinak 			 * real error codes/messages are handled inside
13857711facfSdinak 			 * read_token_objs().
13867711facfSdinak 			 */
13877711facfSdinak 			cryptoerror(LOG_STDERR,
13887711facfSdinak 			    gettext("Unable to convert token objects."));
13897711facfSdinak 			free(id);
13907711facfSdinak 			close_pkcs12(fbio);
13917711facfSdinak 			quick_finish(sess);
13927711facfSdinak 			return (PK_ERR_PK11);
13937711facfSdinak 		}
13947711facfSdinak 
13957711facfSdinak 		/*
13967711facfSdinak 		 * When exporting of cert chains is implemented, these
13977711facfSdinak 		 * messages should be updated accordingly.
13987711facfSdinak 		 */
13997711facfSdinak 		if (mate == ~0UL)
14007711facfSdinak 			(void) fprintf(stdout, gettext(
14017711facfSdinak 			    "Writing object #%d...\n"), i+1);
14027711facfSdinak 		else
14037711facfSdinak 			(void) fprintf(stdout, gettext("Writing object #%d "
14047711facfSdinak 			    "and its certificate...\n"), i+1);
14057711facfSdinak 
14067711facfSdinak 		/* Write object and its certs to the PKCS#12 export file. */
14077711facfSdinak 		if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len,
14087711facfSdinak 		    priv_key, cert, ca, &good_ones, &bad_ones) < 0) {
14097711facfSdinak 			cryptoerror(LOG_STDERR, gettext(
14107711facfSdinak 			    "Unable to write object #%d to export file."), i+1);
14117711facfSdinak 			sk_X509_pop_free(ca, X509_free);
14127711facfSdinak 			free(id);
14137711facfSdinak 			close_pkcs12(fbio);
14147711facfSdinak 			quick_finish(sess);
14157711facfSdinak 			return (PK_ERR_OPENSSL);
14167711facfSdinak 		}
14177711facfSdinak 
14187711facfSdinak 		/* Destroy key id and CA cert chain, done with them. */
14197711facfSdinak 		free(id);
14207711facfSdinak 		id = NULL;
14217711facfSdinak 		sk_X509_pop_free(ca, X509_free);
14227711facfSdinak 		ca = NULL;
14237711facfSdinak 	}
14247711facfSdinak 
14257711facfSdinak 	(void) fprintf(stdout, gettext(
14267711facfSdinak 	    "%d token objects exported, %d errors occurred.\n"),
14277711facfSdinak 	    good_ones, bad_ones);
14287711facfSdinak 
14297711facfSdinak 	/* Close PKCS#12 file. */
14307711facfSdinak 	close_pkcs12(fbio);
14317711facfSdinak 
14327711facfSdinak 	/* Clean up. */
14337711facfSdinak 	quick_finish(sess);
14347711facfSdinak 	return (0);
14357711facfSdinak }
1436