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