xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/export.c (revision 17:003a85e6a25c)
1*17Sdinak /*
2*17Sdinak  * CDDL HEADER START
3*17Sdinak  *
4*17Sdinak  * The contents of this file are subject to the terms of the
5*17Sdinak  * Common Development and Distribution License, Version 1.0 only
6*17Sdinak  * (the "License").  You may not use this file except in compliance
7*17Sdinak  * with the License.
8*17Sdinak  *
9*17Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*17Sdinak  * or http://www.opensolaris.org/os/licensing.
11*17Sdinak  * See the License for the specific language governing permissions
12*17Sdinak  * and limitations under the License.
13*17Sdinak  *
14*17Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
15*17Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*17Sdinak  * If applicable, add the following below this CDDL HEADER, with the
17*17Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
18*17Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
19*17Sdinak  *
20*17Sdinak  * CDDL HEADER END
21*17Sdinak  */
22*17Sdinak /*
23*17Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*17Sdinak  * Use is subject to license terms.
25*17Sdinak  */
26*17Sdinak 
27*17Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*17Sdinak 
29*17Sdinak /*
30*17Sdinak  * This file implements the export operation for this tool.
31*17Sdinak  * The basic flow of the process is to find the soft token,
32*17Sdinak  * log into it, find the PKCS#11 objects in the soft token
33*17Sdinak  * to be exported matching keys with their certificates, export
34*17Sdinak  * them to the PKCS#12 file encrypting them with a file password
35*17Sdinak  * if desired, and log out.
36*17Sdinak  */
37*17Sdinak 
38*17Sdinak #include <stdio.h>
39*17Sdinak #include <stdlib.h>
40*17Sdinak #include <string.h>
41*17Sdinak #include <errno.h>
42*17Sdinak #include <cryptoutil.h>
43*17Sdinak #include <security/cryptoki.h>
44*17Sdinak #include "common.h"
45*17Sdinak #include "biginteger.h"
46*17Sdinak #include "osslcommon.h"
47*17Sdinak #include "p12common.h"
48*17Sdinak #include <openssl/pkcs12.h>
49*17Sdinak 
50*17Sdinak /*
51*17Sdinak  * Writes OpenSSL objects to PKCS#12 file.  The PKCS#11 objects from
52*17Sdinak  * the soft token need to be converted to OpenSSL structures prior
53*17Sdinak  * to this call, since the PKCS#12 routines depend on that format.
54*17Sdinak  * This code is patterned from OpenSSL apps that write PKCS#12 files.
55*17Sdinak  *
56*17Sdinak  * Note:  it's not clear from the usage of all the functions here by
57*17Sdinak  * OpenSSL apps whether these functions have return values or error
58*17Sdinak  * conditions that can be checked.  This function may benefit from
59*17Sdinak  * a closer review at a later time.
60*17Sdinak  */
61*17Sdinak static int
62*17Sdinak write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
63*17Sdinak 	CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert,
64*17Sdinak 	STACK_OF(X509) *ca_certs, int *successes, int *failures)
65*17Sdinak /* ARGSUSED */
66*17Sdinak {
67*17Sdinak 	STACK_OF(PKCS12_SAFEBAG)	*bag_stack = NULL;
68*17Sdinak 	PKCS12_SAFEBAG			*bag = NULL;
69*17Sdinak 	X509				*ca = NULL;
70*17Sdinak 	PKCS7				*cert_authsafe = NULL;
71*17Sdinak 	PKCS8_PRIV_KEY_INFO		*p8 = NULL;
72*17Sdinak 	PKCS7				*key_authsafe = NULL;
73*17Sdinak 	STACK_OF(PKCS7)			*authsafe_stack = NULL;
74*17Sdinak 	PKCS12				*p12_elem = NULL;
75*17Sdinak 	unsigned char			*lab = NULL;
76*17Sdinak 	int				lab_len = 0;
77*17Sdinak 	int				i;
78*17Sdinak 	int				n_writes = 0;
79*17Sdinak 
80*17Sdinak 	cryptodebug("inside write_objs_pkcs12");
81*17Sdinak 
82*17Sdinak 	/* Do not reset *successes or *failures -- keep running totals. */
83*17Sdinak 
84*17Sdinak 	/* If there is nothing to write to the PKCS#12 file, leave. */
85*17Sdinak 	if (cert == NULL && ca_certs == NULL && priv_key == NULL) {
86*17Sdinak 		cryptodebug("nothing to write to export file");
87*17Sdinak 		return (0);
88*17Sdinak 	}
89*17Sdinak 
90*17Sdinak 	/*
91*17Sdinak 	 * Section 1:
92*17Sdinak 	 *
93*17Sdinak 	 * The first PKCS#12 container (safebag) will hold the certificates
94*17Sdinak 	 * associated with this key.  The result of this section is a
95*17Sdinak 	 * PIN-encrypted PKCS#7 container (authsafe).  If there are no
96*17Sdinak 	 * certificates, there is no point in creating the "safebag" or the
97*17Sdinak 	 * "authsafe" so we go to the next section.
98*17Sdinak 	 */
99*17Sdinak 	if (cert != NULL || ca_certs != NULL) {
100*17Sdinak 		/* Start a PKCS#12 safebag container for the certificates. */
101*17Sdinak 		cryptodebug("creating certificate PKCS#12 safebag");
102*17Sdinak 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
103*17Sdinak 		if (bag_stack == NULL) {
104*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
105*17Sdinak 			    "Unable to create PKCS#12 certificate bag."));
106*17Sdinak 			(*failures)++;
107*17Sdinak 			return (-1);
108*17Sdinak 		}
109*17Sdinak 
110*17Sdinak 		/* Add the cert corresponding to private key to bag_stack. */
111*17Sdinak 		if (cert) {
112*17Sdinak 			/* Convert cert from X509 struct to PKCS#12 bag */
113*17Sdinak 			cryptodebug("adding certificate to PKCS#12 safebag");
114*17Sdinak 			bag = PKCS12_x5092certbag(cert);
115*17Sdinak 			if (bag == NULL) {
116*17Sdinak 				cryptoerror(LOG_STDERR, gettext(
117*17Sdinak 				    "Unable to convert certificate to "
118*17Sdinak 				    "PKCS#12 bag."));
119*17Sdinak 				/* Cleanup the safebag. */
120*17Sdinak 				sk_PKCS12_SAFEBAG_pop_free(bag_stack,
121*17Sdinak 				    PKCS12_SAFEBAG_free);
122*17Sdinak 				(*failures)++;
123*17Sdinak 				return (-1);
124*17Sdinak 			}
125*17Sdinak 
126*17Sdinak 			/* Add the key id to the certificate bag. */
127*17Sdinak 			cryptodebug("add key id to PKCS#12 safebag");
128*17Sdinak 			if (!PKCS12_add_localkeyid(bag, id, id_len))
129*17Sdinak 				cryptodebug("error not caught");
130*17Sdinak 
131*17Sdinak 			/* Add the friendly name to the certificate bag. */
132*17Sdinak 			if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) {
133*17Sdinak 				cryptodebug(
134*17Sdinak 				    "label PKCS#12 safebag with friendly name");
135*17Sdinak 				if (!PKCS12_add_friendlyname(bag, (char *)lab,
136*17Sdinak 				    lab_len))
137*17Sdinak 					cryptodebug("error not caught");
138*17Sdinak 			}
139*17Sdinak 
140*17Sdinak 			/* Pile it on the bag_stack. */
141*17Sdinak 			if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
142*17Sdinak 				cryptodebug("error not caught");
143*17Sdinak 
144*17Sdinak 			n_writes++;
145*17Sdinak 		}
146*17Sdinak 
147*17Sdinak 		/* Add all the CA chain certs to the bag_stack. */
148*17Sdinak 		if (ca_certs) {
149*17Sdinak 			cryptodebug("adding CA certificate chain to PKCS#12 "
150*17Sdinak 			    "safebag");
151*17Sdinak 			/*
152*17Sdinak 			 * Go through the stack of CA certs, converting each
153*17Sdinak 			 * one to a PKCS#12 bag and piling them onto the
154*17Sdinak 			 * bag_stack.
155*17Sdinak 			 */
156*17Sdinak 			for (i = 0; i < sk_X509_num(ca_certs); i++) {
157*17Sdinak 				/*
158*17Sdinak 				 * sk_X509_value() is macro that embeds a
159*17Sdinak 				 * cast to (X509 *).  Here it translates
160*17Sdinak 				 * into ((X509 *)sk_value((ca_certs), (i))).
161*17Sdinak 				 * Lint is complaining about the embedded
162*17Sdinak 				 * casting, and to fix it, you need to fix
163*17Sdinak 				 * openssl header files.
164*17Sdinak 				 */
165*17Sdinak 				/* LINTED E_BAD_PTR_CAST_ALIGN */
166*17Sdinak 				ca = sk_X509_value(ca_certs, i);
167*17Sdinak 
168*17Sdinak 				/* Convert CA cert to PKCS#12 bag. */
169*17Sdinak 				cryptodebug("adding CA certificate #%d "
170*17Sdinak 				    "to PKCS#12 safebag", i+1);
171*17Sdinak 				bag = PKCS12_x5092certbag(ca);
172*17Sdinak 				if (bag == NULL) {
173*17Sdinak 					cryptoerror(LOG_STDERR, gettext(
174*17Sdinak 					    "Unable to convert CA certificate "
175*17Sdinak 					    "#%d to PKCS#12 bag."), i+1);
176*17Sdinak 					/* Cleanup the safebag. */
177*17Sdinak 					sk_PKCS12_SAFEBAG_pop_free(bag_stack,
178*17Sdinak 					    PKCS12_SAFEBAG_free);
179*17Sdinak 					(*failures)++;
180*17Sdinak 					return (-1);
181*17Sdinak 				}
182*17Sdinak 
183*17Sdinak 				/* Note CA certs do not have friendly name. */
184*17Sdinak 
185*17Sdinak 				/* Pile it onto the bag_stack. */
186*17Sdinak 				if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
187*17Sdinak 					cryptodebug("error not caught");
188*17Sdinak 
189*17Sdinak 				n_writes++;
190*17Sdinak 			}
191*17Sdinak 		}
192*17Sdinak 
193*17Sdinak 		/* Turn bag_stack of certs into encrypted authsafe. */
194*17Sdinak 		cryptodebug("encrypt certificate PKCS#12 bag into "
195*17Sdinak 		    "PKCS#7 authsafe");
196*17Sdinak 		cert_authsafe = PKCS12_pack_p7encdata(
197*17Sdinak 		    NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL,
198*17Sdinak 		    0, PKCS12_DEFAULT_ITER, bag_stack);
199*17Sdinak 
200*17Sdinak 		/* Clear away this bag_stack, we're done with it. */
201*17Sdinak 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
202*17Sdinak 		bag_stack = NULL;
203*17Sdinak 
204*17Sdinak 		if (cert_authsafe == NULL) {
205*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
206*17Sdinak 			    "Unable to PKCS#7-encrypt certificate bag."));
207*17Sdinak 			(*failures)++;
208*17Sdinak 			return (-1);
209*17Sdinak 		}
210*17Sdinak 	}
211*17Sdinak 
212*17Sdinak 	/*
213*17Sdinak 	 * Section 2:
214*17Sdinak 	 *
215*17Sdinak 	 * The second PKCS#12 container (safebag) will hold the private key
216*17Sdinak 	 * that goes with the certificates above.  The results of this section
217*17Sdinak 	 * is an unencrypted PKCS#7 container (authsafe).  If there is no
218*17Sdinak 	 * private key, there is no point in creating the "safebag" or the
219*17Sdinak 	 * "authsafe" so we go to the next section.
220*17Sdinak 	 */
221*17Sdinak 	if (priv_key != NULL) {
222*17Sdinak 		/* Make a PKCS#8 shrouded key bag. */
223*17Sdinak 		cryptodebug("create PKCS#8 shrouded key out of private key");
224*17Sdinak 		p8 = EVP_PKEY2PKCS8(priv_key);
225*17Sdinak 		if (p8 == NULL) {
226*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
227*17Sdinak 			    "Unable to create PKCS#8 shrouded key for "
228*17Sdinak 			    "private key."));
229*17Sdinak 			(*failures)++;
230*17Sdinak 			return (-1);
231*17Sdinak 		}
232*17Sdinak 
233*17Sdinak 		/* Put the shrouded key into a PKCS#12 bag. */
234*17Sdinak 		cryptodebug("convert shrouded key to PKCS#12 bag");
235*17Sdinak 		bag = PKCS12_MAKE_SHKEYBAG(
236*17Sdinak 		    NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin,
237*17Sdinak 		    -1, NULL, 0, PKCS12_DEFAULT_ITER, p8);
238*17Sdinak 
239*17Sdinak 		/* Clean up the PKCS#8 shrouded key, don't need it now. */
240*17Sdinak 		PKCS8_PRIV_KEY_INFO_free(p8);
241*17Sdinak 		p8 = NULL;
242*17Sdinak 
243*17Sdinak 		if (bag == NULL) {
244*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
245*17Sdinak 			    "Unable to convert private key to PKCS#12 bag."));
246*17Sdinak 			(*failures)++;
247*17Sdinak 			return (-1);
248*17Sdinak 		}
249*17Sdinak 
250*17Sdinak 		/* Add the key id to the certificate bag. */
251*17Sdinak 		cryptodebug("add key id to PKCS#12 safebag");
252*17Sdinak 		if (!PKCS12_add_localkeyid(bag, id, id_len))
253*17Sdinak 			cryptodebug("error not caught");
254*17Sdinak 
255*17Sdinak 		/* Add the cert friendly name to the private key bag. */
256*17Sdinak 		if (lab != NULL) {
257*17Sdinak 			cryptodebug("label PKCS#12 safebag with friendly name");
258*17Sdinak 			if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len))
259*17Sdinak 				cryptodebug("error not caught");
260*17Sdinak 		}
261*17Sdinak 
262*17Sdinak 		/* Start a PKCS#12 safebag container for the private key. */
263*17Sdinak 		cryptodebug("creating private key PKCS#12 safebag");
264*17Sdinak 		bag_stack = sk_PKCS12_SAFEBAG_new_null();
265*17Sdinak 		if (bag_stack == NULL) {
266*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
267*17Sdinak 			    "Unable to create PKCS#12 private key bag."));
268*17Sdinak 			(*failures)++;
269*17Sdinak 			return (-1);
270*17Sdinak 		}
271*17Sdinak 
272*17Sdinak 		/* Pile on the private key on the bag_stack. */
273*17Sdinak 		if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
274*17Sdinak 			cryptodebug("error not caught");
275*17Sdinak 
276*17Sdinak 		/* Turn bag_stack with private key into unencrypted authsafe. */
277*17Sdinak 		cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe");
278*17Sdinak 		key_authsafe = PKCS12_pack_p7data(bag_stack);
279*17Sdinak 
280*17Sdinak 		/* Clear away this bag_stack, we're done with it. */
281*17Sdinak 		sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
282*17Sdinak 		bag_stack = NULL;
283*17Sdinak 
284*17Sdinak 		if (key_authsafe == NULL) {
285*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
286*17Sdinak 			    "Unable to PKCS#7-convert private key bag."));
287*17Sdinak 			(*failures)++;
288*17Sdinak 			return (-1);
289*17Sdinak 		}
290*17Sdinak 
291*17Sdinak 		n_writes++;
292*17Sdinak 	}
293*17Sdinak 
294*17Sdinak 	/*
295*17Sdinak 	 * Section 3:
296*17Sdinak 	 *
297*17Sdinak 	 * This is where the two PKCS#7 containers, one for the certificates
298*17Sdinak 	 * and one for the private key, are put together into a PKCS#12
299*17Sdinak 	 * element.  This final PKCS#12 element is written to the export file.
300*17Sdinak 	 */
301*17Sdinak 	/* Start a PKCS#7 stack. */
302*17Sdinak 	cryptodebug("create PKCS#7 authsafe for private key and certificates");
303*17Sdinak 	authsafe_stack = sk_PKCS7_new_null();
304*17Sdinak 	if (authsafe_stack == NULL) {
305*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
306*17Sdinak 		    "Unable to create PKCS#7 container for private key "
307*17Sdinak 		    "and certificates."));
308*17Sdinak 		(*failures)++;
309*17Sdinak 		return (-1);
310*17Sdinak 	}
311*17Sdinak 
312*17Sdinak 	/* Put certificates and private key into PKCS#7 stack. */
313*17Sdinak 	if (key_authsafe != NULL) {
314*17Sdinak 		cryptodebug("put private key authsafe into PKCS#7 container");
315*17Sdinak 		if (!sk_PKCS7_push(authsafe_stack, key_authsafe))
316*17Sdinak 			cryptodebug("error not caught");
317*17Sdinak 	}
318*17Sdinak 	if (cert_authsafe != NULL) {
319*17Sdinak 		cryptodebug("put certificate authsafe into PKCS#7 container");
320*17Sdinak 		if (!sk_PKCS7_push(authsafe_stack, cert_authsafe))
321*17Sdinak 			cryptodebug("error not caught");
322*17Sdinak 	}
323*17Sdinak 
324*17Sdinak 	/* Create PKCS#12 element out of PKCS#7 stack. */
325*17Sdinak 	cryptodebug("create PKCS#12 element for export file");
326*17Sdinak 	p12_elem = PKCS12_init(NID_pkcs7_data);
327*17Sdinak 	if (p12_elem == NULL) {
328*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
329*17Sdinak 		    "Unable to create PKCS#12 element for export file."));
330*17Sdinak 		sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
331*17Sdinak 		(*failures)++;
332*17Sdinak 		return (-1);
333*17Sdinak 	}
334*17Sdinak 
335*17Sdinak 	/* Put the PKCS#7 stack into the PKCS#12 element. */
336*17Sdinak 	if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack))
337*17Sdinak 		cryptodebug("error not caught");
338*17Sdinak 
339*17Sdinak 	/* Clear away the PKCS#7 stack, we're done with it. */
340*17Sdinak 	sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
341*17Sdinak 	authsafe_stack = NULL;
342*17Sdinak 
343*17Sdinak 	/* Set the integrity MAC on the PKCS#12 element. */
344*17Sdinak 	cryptodebug("setting MAC for PKCS#12 element");
345*17Sdinak 	if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0,
346*17Sdinak 	    PKCS12_DEFAULT_ITER, NULL))
347*17Sdinak 		cryptodebug("error not caught");
348*17Sdinak 
349*17Sdinak 	/* Write the PKCS#12 element to the export file. */
350*17Sdinak 	cryptodebug("writing PKCS#12 element to export file");
351*17Sdinak 	if (!i2d_PKCS12_bio(fbio, p12_elem))
352*17Sdinak 		cryptodebug("error not caught");
353*17Sdinak 
354*17Sdinak 	(*successes) += n_writes;
355*17Sdinak 
356*17Sdinak 	/* Clear away the PKCS#12 element. */
357*17Sdinak 	PKCS12_free(p12_elem);
358*17Sdinak 	return (0);
359*17Sdinak }
360*17Sdinak 
361*17Sdinak /*
362*17Sdinak  * Get token objects: private key, its cert, and its cert chain.
363*17Sdinak  */
364*17Sdinak static CK_RV
365*17Sdinak get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
366*17Sdinak 	CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain,
367*17Sdinak 	CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len)
368*17Sdinak {
369*17Sdinak 	CK_RV			rv = CKR_OK;
370*17Sdinak 	CK_ATTRIBUTE		keyid_attr[1] = {
371*17Sdinak 		{ CKA_ID, NULL, 0 }
372*17Sdinak 	    };
373*17Sdinak 	static CK_OBJECT_CLASS	class = CKO_CERTIFICATE;
374*17Sdinak 	static CK_CERTIFICATE_TYPE	certtype = CKC_X_509;
375*17Sdinak 	CK_ATTRIBUTE		cert_attr[4] = {
376*17Sdinak 		{ CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) },
377*17Sdinak 		{ CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
378*17Sdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
379*17Sdinak 		{ CKA_ID, NULL, 0 }
380*17Sdinak 	    };
381*17Sdinak 	CK_ULONG	num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE);
382*17Sdinak 	CK_OBJECT_HANDLE	cert = ~0UL;
383*17Sdinak 	CK_ULONG		num = 0;
384*17Sdinak 
385*17Sdinak 	cryptodebug("inside get_token_objs");
386*17Sdinak 
387*17Sdinak 	/* Get the size of the object's CKA_ID field first. */
388*17Sdinak 	cryptodebug("getting CKA_ID size for object 0x%x", obj);
389*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
390*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get size of object"
391*17Sdinak 		    " key id (%s)."), pkcs11_strerror(rv));
392*17Sdinak 		return (rv);
393*17Sdinak 	}
394*17Sdinak 
395*17Sdinak 	/* Allocate the space needed for the key id. */
396*17Sdinak 	if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) {
397*17Sdinak 		cryptoerror(LOG_STDERR, "%s.", strerror(errno));
398*17Sdinak 		return (CKR_HOST_MEMORY);
399*17Sdinak 	}
400*17Sdinak 
401*17Sdinak 	/* Get the CKA_ID field to match obj with its cert. */
402*17Sdinak 	cryptodebug("getting CKA_ID attribute for object 0x%x", obj);
403*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
404*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get object "
405*17Sdinak 		    "key id (%s)."), pkcs11_strerror(rv));
406*17Sdinak 		free(keyid_attr[0].pValue);
407*17Sdinak 		return (rv);
408*17Sdinak 	}
409*17Sdinak 
410*17Sdinak 	/* Now try to find any certs that have the same id. */
411*17Sdinak 	cryptodebug("searching for certificates with same CKA_ID");
412*17Sdinak 	cert_attr[3].pValue = keyid_attr[0].pValue;
413*17Sdinak 	cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen;
414*17Sdinak 	if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) {
415*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to initialize "
416*17Sdinak 		    "certificate search (%s)."), pkcs11_strerror(rv));
417*17Sdinak 		free(keyid_attr[0].pValue);
418*17Sdinak 		return (rv);
419*17Sdinak 	}
420*17Sdinak 
421*17Sdinak 	/* Find the first cert that matches the key id. */
422*17Sdinak 	if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) {
423*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Certificate search failed "
424*17Sdinak 		    "(%s)."), pkcs11_strerror(rv));
425*17Sdinak 		free(keyid_attr[0].pValue);
426*17Sdinak 		return (rv);
427*17Sdinak 	}
428*17Sdinak 
429*17Sdinak 	(void) C_FindObjectsFinal(sess);
430*17Sdinak 
431*17Sdinak 	*id = keyid_attr[0].pValue;
432*17Sdinak 	*id_len = keyid_attr[0].ulValueLen;
433*17Sdinak 
434*17Sdinak 	*mate = (num == 1) ? cert : ~0UL;
435*17Sdinak 
436*17Sdinak 	/* We currently do not find all the certs in the chain. */
437*17Sdinak 	*chain_len = 0;
438*17Sdinak 	*chain = NULL;
439*17Sdinak 
440*17Sdinak 	return (CKR_OK);
441*17Sdinak }
442*17Sdinak 
443*17Sdinak /*
444*17Sdinak  * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM.
445*17Sdinak  * "to" should be the address of a ptr init'ed to NULL to
446*17Sdinak  * receive the BIGNUM, e.g.,
447*17Sdinak  *	biginteger_t	from;
448*17Sdinak  * 	BIGNUM	*foo = NULL;
449*17Sdinak  *	cvt_bigint2bn(&from, &foo);
450*17Sdinak  */
451*17Sdinak static int
452*17Sdinak cvt_bigint2bn(biginteger_t *from, BIGNUM **to)
453*17Sdinak {
454*17Sdinak 	BIGNUM	*temp = NULL;
455*17Sdinak 
456*17Sdinak 	cryptodebug("inside cvt_bigint2bn");
457*17Sdinak 
458*17Sdinak 	if (from == NULL || to == NULL)
459*17Sdinak 		return (-1);
460*17Sdinak 
461*17Sdinak 	cryptodebug("calling BN_bin2bn");
462*17Sdinak 	if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) ==
463*17Sdinak 	    NULL)
464*17Sdinak 		return (-1);
465*17Sdinak 
466*17Sdinak 	*to = temp;
467*17Sdinak 	return (0);
468*17Sdinak }
469*17Sdinak 
470*17Sdinak /*
471*17Sdinak  * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure.
472*17Sdinak  */
473*17Sdinak static CK_RV
474*17Sdinak cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
475*17Sdinak {
476*17Sdinak 	CK_RV		rv = CKR_OK;
477*17Sdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
478*17Sdinak 	RSA		*rsa = NULL;		/* OpenSSL representation */
479*17Sdinak 	biginteger_t	mod = { NULL, 0 };	/* required */
480*17Sdinak 	biginteger_t	pubexp = { NULL, 0 };	/* required */
481*17Sdinak 	biginteger_t	priexp = { NULL, 0 };	/* optional */
482*17Sdinak 	biginteger_t	prime1 = { NULL, 0 };	/* optional */
483*17Sdinak 	biginteger_t	prime2 = { NULL, 0 };	/* optional */
484*17Sdinak 	biginteger_t	exp1 = { NULL, 0 };	/* optional */
485*17Sdinak 	biginteger_t	exp2 = { NULL, 0 };	/* optional */
486*17Sdinak 	biginteger_t	coef = { NULL, 0 };	/* optional */
487*17Sdinak 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
488*17Sdinak 		{ CKA_MODULUS, NULL, 0 },
489*17Sdinak 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
490*17Sdinak 		{ CKA_PRIVATE_EXPONENT, NULL, 0 },	/* optional */
491*17Sdinak 		{ CKA_PRIME_1, NULL, 0 },		/*  |  */
492*17Sdinak 		{ CKA_PRIME_2, NULL, 0 },		/*  |  */
493*17Sdinak 		{ CKA_EXPONENT_1, NULL, 0 },		/*  |  */
494*17Sdinak 		{ CKA_EXPONENT_2, NULL, 0 },		/*  |  */
495*17Sdinak 		{ CKA_COEFFICIENT, NULL, 0 }		/*  V  */
496*17Sdinak 	    };
497*17Sdinak 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
498*17Sdinak 	int		i;
499*17Sdinak 
500*17Sdinak 	cryptodebug("inside cvt_rsa2evp_pkey");
501*17Sdinak 
502*17Sdinak 	cryptodebug("calling RSA_new");
503*17Sdinak 	if ((rsa = RSA_new()) == NULL) {
504*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
505*17Sdinak 		    "Unable to allocate internal RSA structure."));
506*17Sdinak 		return (CKR_HOST_MEMORY);
507*17Sdinak 	}
508*17Sdinak 
509*17Sdinak 	/* Get the sizes of the attributes we need. */
510*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
511*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
512*17Sdinak 	    CKR_OK) {
513*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
514*17Sdinak 		    "Unable to get RSA private key attribute sizes (%s)."),
515*17Sdinak 		    pkcs11_strerror(rv));
516*17Sdinak 		return (rv);
517*17Sdinak 	}
518*17Sdinak 
519*17Sdinak 	/* Allocate memory for each attribute. */
520*17Sdinak 	for (i = 0; i < count; i++) {
521*17Sdinak 		if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
522*17Sdinak 		    rsa_pri_attrs[i].ulValueLen == 0) {
523*17Sdinak 			cryptodebug("cvt_rsa2evp_pkey: *** should not happen");
524*17Sdinak 			rsa_pri_attrs[i].ulValueLen = 0;
525*17Sdinak 			continue;
526*17Sdinak 		}
527*17Sdinak 		if ((rsa_pri_attrs[i].pValue =
528*17Sdinak 		    malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
529*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
530*17Sdinak 			return (CKR_HOST_MEMORY);
531*17Sdinak 		}
532*17Sdinak 	}
533*17Sdinak 
534*17Sdinak 	/* Now really get the attributes. */
535*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
536*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
537*17Sdinak 	    CKR_OK) {
538*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
539*17Sdinak 		    "Unable to get RSA private key attributes (%s)."),
540*17Sdinak 		    pkcs11_strerror(rv));
541*17Sdinak 		return (rv);
542*17Sdinak 	}
543*17Sdinak 
544*17Sdinak 	/*
545*17Sdinak 	 * Fill in all the temp variables.  Modulus and public exponent
546*17Sdinak 	 * are required.  The rest are optional.
547*17Sdinak 	 */
548*17Sdinak 	i = 0;
549*17Sdinak 	copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod);
550*17Sdinak 	copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp);
551*17Sdinak 
552*17Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
553*17Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
554*17Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp);
555*17Sdinak 	i++;
556*17Sdinak 
557*17Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
558*17Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
559*17Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1);
560*17Sdinak 	i++;
561*17Sdinak 
562*17Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
563*17Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
564*17Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2);
565*17Sdinak 	i++;
566*17Sdinak 
567*17Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
568*17Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
569*17Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1);
570*17Sdinak 	i++;
571*17Sdinak 
572*17Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
573*17Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
574*17Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2);
575*17Sdinak 	i++;
576*17Sdinak 
577*17Sdinak 	if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
578*17Sdinak 	    rsa_pri_attrs[i].ulValueLen != 0)
579*17Sdinak 		copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef);
580*17Sdinak 	i++;
581*17Sdinak 
582*17Sdinak 	/* Start the conversion to internal OpenSSL RSA structure. */
583*17Sdinak 
584*17Sdinak 	/* Modulus n */
585*17Sdinak 	if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) {
586*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
587*17Sdinak 		    "Unable to convert RSA private key modulus."));
588*17Sdinak 		return (CKR_GENERAL_ERROR);
589*17Sdinak 	}
590*17Sdinak 
591*17Sdinak 	/* Public exponent e */
592*17Sdinak 	if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) {
593*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
594*17Sdinak 		    "Unable to convert RSA private key public exponent."));
595*17Sdinak 		return (CKR_GENERAL_ERROR);
596*17Sdinak 	}
597*17Sdinak 
598*17Sdinak 	/* Private exponent e */
599*17Sdinak 	if (priexp.big_value != NULL) {
600*17Sdinak 		if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) {
601*17Sdinak 			cryptoerror(LOG_STDERR, gettext("Unable to convert "
602*17Sdinak 			    "RSA private key private exponent."));
603*17Sdinak 			return (CKR_GENERAL_ERROR);
604*17Sdinak 		}
605*17Sdinak 	} else
606*17Sdinak 		cryptodebug("no RSA private key private exponent");
607*17Sdinak 
608*17Sdinak 	/* Prime p */
609*17Sdinak 	if (prime1.big_value != NULL) {
610*17Sdinak 		if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) {
611*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
612*17Sdinak 			    "Unable to convert RSA private key prime 1."));
613*17Sdinak 			return (CKR_GENERAL_ERROR);
614*17Sdinak 		}
615*17Sdinak 	} else
616*17Sdinak 		cryptodebug("no RSA private key prime 1");
617*17Sdinak 
618*17Sdinak 	/* Prime q */
619*17Sdinak 	if (prime2.big_value != NULL) {
620*17Sdinak 		if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) {
621*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
622*17Sdinak 			    "Unable to convert RSA private key prime 2."));
623*17Sdinak 			return (CKR_GENERAL_ERROR);
624*17Sdinak 		}
625*17Sdinak 	} else
626*17Sdinak 		cryptodebug("no RSA private key prime 2");
627*17Sdinak 
628*17Sdinak 	/* Private exponent d modulo p-1 */
629*17Sdinak 	if (exp1.big_value != NULL) {
630*17Sdinak 		if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) {
631*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
632*17Sdinak 			    "Unable to convert RSA private key exponent 1."));
633*17Sdinak 			return (CKR_GENERAL_ERROR);
634*17Sdinak 		}
635*17Sdinak 	} else
636*17Sdinak 		cryptodebug("no RSA private key exponent 1");
637*17Sdinak 
638*17Sdinak 	/* Private exponent d modulo q-1 */
639*17Sdinak 	if (exp2.big_value != NULL) {
640*17Sdinak 		if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) {
641*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
642*17Sdinak 			    "Unable to convert RSA private key exponent 2."));
643*17Sdinak 			return (CKR_GENERAL_ERROR);
644*17Sdinak 		}
645*17Sdinak 	} else
646*17Sdinak 		cryptodebug("no RSA private key exponent 2");
647*17Sdinak 
648*17Sdinak 	/* CRT coefficient q-inverse mod p */
649*17Sdinak 	if (coef.big_value != NULL) {
650*17Sdinak 		if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) {
651*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
652*17Sdinak 			    "Unable to convert RSA private key coefficient."));
653*17Sdinak 			return (CKR_GENERAL_ERROR);
654*17Sdinak 		}
655*17Sdinak 	} else
656*17Sdinak 		cryptodebug("no RSA private key coefficient");
657*17Sdinak 
658*17Sdinak 	/* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */
659*17Sdinak 	cryptodebug("calling EVP_PKEY_new");
660*17Sdinak 	if ((key = EVP_PKEY_new()) == NULL) {
661*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
662*17Sdinak 		    "Unable to allocate internal EVP_PKEY structure."));
663*17Sdinak 		return (CKR_HOST_MEMORY);
664*17Sdinak 	}
665*17Sdinak 
666*17Sdinak 	/* Put the RSA struct into the EVP_PKEY struct and return it. */
667*17Sdinak 	cryptodebug("calling EVP_PKEY_set1_RSA");
668*17Sdinak 	(void) EVP_PKEY_set1_RSA(key, rsa);
669*17Sdinak 
670*17Sdinak 	*pk = key;
671*17Sdinak 	return (CKR_OK);
672*17Sdinak }
673*17Sdinak 
674*17Sdinak /*
675*17Sdinak  * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure.
676*17Sdinak  */
677*17Sdinak static CK_RV
678*17Sdinak cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
679*17Sdinak {
680*17Sdinak 	CK_RV		rv = CKR_OK;
681*17Sdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
682*17Sdinak 	DSA		*dsa = NULL;		/* OpenSSL representation */
683*17Sdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
684*17Sdinak 	biginteger_t	subprime = { NULL, 0 };	/* required */
685*17Sdinak 	biginteger_t	base = { NULL, 0 };	/* required */
686*17Sdinak 	biginteger_t	value = { NULL, 0 };	/* required */
687*17Sdinak 	CK_ATTRIBUTE	dsa_pri_attrs[4] = {
688*17Sdinak 		{ CKA_PRIME, NULL, 0 },
689*17Sdinak 		{ CKA_SUBPRIME, NULL, 0 },
690*17Sdinak 		{ CKA_BASE, NULL, 0 },
691*17Sdinak 		{ CKA_VALUE, NULL, 0 }
692*17Sdinak 	    };
693*17Sdinak 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
694*17Sdinak 	int		i;
695*17Sdinak 
696*17Sdinak 	cryptodebug("inside cvt_dsa2evp_pkey");
697*17Sdinak 
698*17Sdinak 	cryptodebug("calling DSA_new");
699*17Sdinak 	if ((dsa = DSA_new()) == NULL) {
700*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
701*17Sdinak 		    "Unable to allocate internal DSA structure."));
702*17Sdinak 		return (CKR_HOST_MEMORY);
703*17Sdinak 	}
704*17Sdinak 
705*17Sdinak 	/* Get the sizes of the attributes we need. */
706*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
707*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
708*17Sdinak 	    CKR_OK) {
709*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
710*17Sdinak 		    "Unable to get DSA private key object attributes (%s)."),
711*17Sdinak 		    pkcs11_strerror(rv));
712*17Sdinak 		return (rv);
713*17Sdinak 	}
714*17Sdinak 
715*17Sdinak 	/* Allocate memory for each attribute. */
716*17Sdinak 	for (i = 0; i < count; i++) {
717*17Sdinak 		if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
718*17Sdinak 		    dsa_pri_attrs[i].ulValueLen == 0) {
719*17Sdinak 			cryptodebug("cvt_dsa2evp_pkey:  *** should not happen");
720*17Sdinak 			dsa_pri_attrs[i].ulValueLen = 0;
721*17Sdinak 			continue;
722*17Sdinak 		}
723*17Sdinak 		if ((dsa_pri_attrs[i].pValue =
724*17Sdinak 		    malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
725*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
726*17Sdinak 			return (CKR_HOST_MEMORY);
727*17Sdinak 		}
728*17Sdinak 	}
729*17Sdinak 
730*17Sdinak 	/* Now really get the attributes. */
731*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
732*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
733*17Sdinak 	    CKR_OK) {
734*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
735*17Sdinak 		    "Unable to get DSA private key attributes (%s)."),
736*17Sdinak 		    pkcs11_strerror(rv));
737*17Sdinak 		return (rv);
738*17Sdinak 	}
739*17Sdinak 
740*17Sdinak 	/* Fill in all the temp variables.  They are all required. */
741*17Sdinak 	i = 0;
742*17Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime);
743*17Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime);
744*17Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base);
745*17Sdinak 	copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value);
746*17Sdinak 
747*17Sdinak 	/* Start the conversion to internal OpenSSL DSA structure. */
748*17Sdinak 
749*17Sdinak 	/* Prime p */
750*17Sdinak 	if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) {
751*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
752*17Sdinak 		    "Unable to convert DSA private key prime."));
753*17Sdinak 		return (CKR_GENERAL_ERROR);
754*17Sdinak 	}
755*17Sdinak 
756*17Sdinak 	/* Subprime q */
757*17Sdinak 	if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) {
758*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
759*17Sdinak 		    "Unable to convert DSA private key subprime."));
760*17Sdinak 		return (CKR_GENERAL_ERROR);
761*17Sdinak 	}
762*17Sdinak 
763*17Sdinak 	/* Base g */
764*17Sdinak 	if (cvt_bigint2bn(&base, &(dsa->g)) < 0) {
765*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
766*17Sdinak 		    "Unable to convert DSA private key base."));
767*17Sdinak 		return (CKR_GENERAL_ERROR);
768*17Sdinak 	}
769*17Sdinak 
770*17Sdinak 	/* Private key x */
771*17Sdinak 	if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) {
772*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
773*17Sdinak 		    "Unable to convert DSA private key value."));
774*17Sdinak 		return (CKR_GENERAL_ERROR);
775*17Sdinak 	}
776*17Sdinak 
777*17Sdinak 	/* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */
778*17Sdinak 	cryptodebug("calling EVP_PKEY_new");
779*17Sdinak 	if ((key = EVP_PKEY_new()) == NULL) {
780*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
781*17Sdinak 		    "Unable to allocate internal EVP_PKEY structure."));
782*17Sdinak 		return (CKR_HOST_MEMORY);
783*17Sdinak 	}
784*17Sdinak 
785*17Sdinak 	/* Put the DSA struct into the EVP_PKEY struct and return it. */
786*17Sdinak 	cryptodebug("calling EVP_PKEY_set1_DSA");
787*17Sdinak 	(void) EVP_PKEY_set1_DSA(key, dsa);
788*17Sdinak 
789*17Sdinak 	*pk = key;
790*17Sdinak 	return (CKR_OK);
791*17Sdinak }
792*17Sdinak 
793*17Sdinak /*
794*17Sdinak  * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure.
795*17Sdinak  */
796*17Sdinak static CK_RV
797*17Sdinak cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
798*17Sdinak {
799*17Sdinak 	CK_RV		rv = CKR_OK;
800*17Sdinak 	EVP_PKEY	*key = NULL;		/* OpenSSL representation */
801*17Sdinak 	DH		*dh = NULL;		/* OpenSSL representation */
802*17Sdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
803*17Sdinak 	biginteger_t	base = { NULL, 0 };	/* required */
804*17Sdinak 	biginteger_t	value = { NULL, 0 };	/* required */
805*17Sdinak 	CK_ATTRIBUTE	dh_pri_attrs[3] = {
806*17Sdinak 		{ CKA_PRIME, NULL, 0 },
807*17Sdinak 		{ CKA_BASE, NULL, 0 },
808*17Sdinak 		{ CKA_VALUE, NULL, 0 }
809*17Sdinak 	    };
810*17Sdinak 	CK_ULONG	count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
811*17Sdinak 	int		i;
812*17Sdinak 
813*17Sdinak 	cryptodebug("inside cvt_dh2evp_pkey");
814*17Sdinak 
815*17Sdinak 	cryptodebug("calling DH_new");
816*17Sdinak 	if ((dh = DH_new()) == NULL) {
817*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
818*17Sdinak 		    "Unable to allocate internal DH structure."));
819*17Sdinak 		return (CKR_HOST_MEMORY);
820*17Sdinak 	}
821*17Sdinak 
822*17Sdinak 	/* Get the sizes of the attributes we need. */
823*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
824*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
825*17Sdinak 	    CKR_OK) {
826*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
827*17Sdinak 		    "Unable to get DH private key object attributes (%s)."),
828*17Sdinak 		    pkcs11_strerror(rv));
829*17Sdinak 		return (rv);
830*17Sdinak 	}
831*17Sdinak 
832*17Sdinak 	/* Allocate memory for each attribute. */
833*17Sdinak 	for (i = 0; i < count; i++) {
834*17Sdinak 		if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
835*17Sdinak 		    dh_pri_attrs[i].ulValueLen == 0) {
836*17Sdinak 			cryptodebug("cvt_dh2evp_pkey: ***should not happen");
837*17Sdinak 			dh_pri_attrs[i].ulValueLen = 0;
838*17Sdinak 			continue;
839*17Sdinak 		}
840*17Sdinak 		if ((dh_pri_attrs[i].pValue =
841*17Sdinak 		    malloc(dh_pri_attrs[i].ulValueLen)) == NULL) {
842*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
843*17Sdinak 			return (CKR_HOST_MEMORY);
844*17Sdinak 		}
845*17Sdinak 	}
846*17Sdinak 
847*17Sdinak 	/* Now really get the attributes. */
848*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
849*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
850*17Sdinak 	    CKR_OK) {
851*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
852*17Sdinak 		    "Unable to get DH private key attributes (%s)."),
853*17Sdinak 		    pkcs11_strerror(rv));
854*17Sdinak 		return (rv);
855*17Sdinak 	}
856*17Sdinak 
857*17Sdinak 	/* Fill in all the temp variables.  They are all required. */
858*17Sdinak 	i = 0;
859*17Sdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime);
860*17Sdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base);
861*17Sdinak 	copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value);
862*17Sdinak 
863*17Sdinak 	/* Start the conversion to internal OpenSSL DH structure. */
864*17Sdinak 
865*17Sdinak 	/* Prime p */
866*17Sdinak 	if (cvt_bigint2bn(&prime, &(dh->p)) < 0) {
867*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
868*17Sdinak 		    "Unable to convert DH private key prime."));
869*17Sdinak 		return (CKR_GENERAL_ERROR);
870*17Sdinak 	}
871*17Sdinak 
872*17Sdinak 	/* Base g */
873*17Sdinak 	if (cvt_bigint2bn(&base, &(dh->g)) < 0) {
874*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
875*17Sdinak 		    "Unable to convert DH private key base."));
876*17Sdinak 		return (CKR_GENERAL_ERROR);
877*17Sdinak 	}
878*17Sdinak 
879*17Sdinak 	/* Private value x */
880*17Sdinak 	if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) {
881*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
882*17Sdinak 		    "Unable to convert DH private key value."));
883*17Sdinak 		return (CKR_GENERAL_ERROR);
884*17Sdinak 	}
885*17Sdinak 
886*17Sdinak 	/* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */
887*17Sdinak 	cryptodebug("calling EVP_PKEY_new");
888*17Sdinak 	if ((key = EVP_PKEY_new()) == NULL) {
889*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
890*17Sdinak 		    "Unable to allocate internal EVP_PKEY structure."));
891*17Sdinak 		return (CKR_HOST_MEMORY);
892*17Sdinak 	}
893*17Sdinak 
894*17Sdinak 	/* Put the DH struct into the EVP_PKEY struct and return it. */
895*17Sdinak 	cryptodebug("calling EVP_PKEY_set1_DH");
896*17Sdinak 	(void) EVP_PKEY_set1_DH(key, dh);
897*17Sdinak 
898*17Sdinak 	*pk = key;
899*17Sdinak 	return (CKR_OK);
900*17Sdinak }
901*17Sdinak 
902*17Sdinak /*
903*17Sdinak  * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure.
904*17Sdinak  */
905*17Sdinak static CK_RV
906*17Sdinak cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
907*17Sdinak {
908*17Sdinak 	CK_RV			rv = CKR_OK;
909*17Sdinak 	static CK_KEY_TYPE	keytype = 0;
910*17Sdinak 	CK_ATTRIBUTE		keytype_attr[1] = {
911*17Sdinak 		{ CKA_KEY_TYPE, &keytype, sizeof (keytype) }
912*17Sdinak 	    };
913*17Sdinak 
914*17Sdinak 	cryptodebug("inside cvt_obj2evp_pkey");
915*17Sdinak 
916*17Sdinak 	/* Find out the key type to do the right conversion. */
917*17Sdinak 	cryptodebug("calling C_GetAttributeValue");
918*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) !=
919*17Sdinak 	    CKR_OK) {
920*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
921*17Sdinak 		    "Unable to get token object key type (%s)."),
922*17Sdinak 		    pkcs11_strerror(rv));
923*17Sdinak 		return (rv);
924*17Sdinak 	}
925*17Sdinak 
926*17Sdinak 	switch (keytype) {
927*17Sdinak 	case CKK_RSA:
928*17Sdinak 		cryptodebug("converting RSA key");
929*17Sdinak 		return (cvt_rsa2evp_pkey(sess, obj, pk));
930*17Sdinak 	case CKK_DSA:
931*17Sdinak 		cryptodebug("converting DSA key");
932*17Sdinak 		return (cvt_dsa2evp_pkey(sess, obj, pk));
933*17Sdinak 	case CKK_DH:
934*17Sdinak 		cryptodebug("converting DH key");
935*17Sdinak 		return (cvt_dh2evp_pkey(sess, obj, pk));
936*17Sdinak 	default:
937*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
938*17Sdinak 		    "Private key type 0x%02x conversion not supported."),
939*17Sdinak 		    keytype);
940*17Sdinak 		return (CKR_GENERAL_ERROR);
941*17Sdinak 	}
942*17Sdinak }
943*17Sdinak 
944*17Sdinak /*
945*17Sdinak  * Convert PKCS#11 certificate object to OpenSSL X509 structure.
946*17Sdinak  */
947*17Sdinak static CK_RV
948*17Sdinak cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c)
949*17Sdinak {
950*17Sdinak 	CK_RV			rv = CKR_OK;
951*17Sdinak 	X509			*cert = NULL;	/* OpenSSL representation */
952*17Sdinak 	X509			*temp_cert = NULL;
953*17Sdinak 	CK_BYTE			*subject = NULL;
954*17Sdinak 	CK_ULONG		subject_len = 0;
955*17Sdinak 	CK_BYTE			*value = NULL;
956*17Sdinak 	CK_ULONG		value_len = 0;
957*17Sdinak 	CK_BYTE			*label = NULL;
958*17Sdinak 	CK_ULONG		label_len = 0;
959*17Sdinak 	CK_BYTE			*id = NULL;
960*17Sdinak 	CK_ULONG		id_len = 0;
961*17Sdinak 	CK_BYTE			*issuer = NULL;
962*17Sdinak 	CK_ULONG		issuer_len = 0;
963*17Sdinak 	CK_BYTE			*serial = NULL;
964*17Sdinak 	CK_ULONG		serial_len = 0;
965*17Sdinak 	CK_ATTRIBUTE		cert_attrs[6] = {
966*17Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* required */
967*17Sdinak 		{ CKA_VALUE, NULL, 0 },			/* required */
968*17Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
969*17Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
970*17Sdinak 		{ CKA_ISSUER, NULL, 0 },		/* optional */
971*17Sdinak 		{ CKA_SERIAL_NUMBER, NULL, 0 }		/* optional */
972*17Sdinak 	    };
973*17Sdinak 	CK_ULONG	count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
974*17Sdinak 	int		i = 0;
975*17Sdinak 	X509_NAME	*ssl_subject = NULL;
976*17Sdinak 	X509_NAME	*ssl_issuer = NULL;
977*17Sdinak 	ASN1_INTEGER	*ssl_serial = NULL;
978*17Sdinak 
979*17Sdinak 	cryptodebug("inside cvt_cert2x509");
980*17Sdinak 
981*17Sdinak 	cryptodebug("calling X509_new");
982*17Sdinak 	if ((cert = X509_new()) == NULL) {
983*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
984*17Sdinak 		    "Unable to allocate internal X509 structure."));
985*17Sdinak 		return (CKR_HOST_MEMORY);
986*17Sdinak 	}
987*17Sdinak 
988*17Sdinak 	/* Get the sizes of the attributes we need. */
989*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
990*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
991*17Sdinak 	    CKR_OK) {
992*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
993*17Sdinak 		    "Unable to get certificate attribute sizes (%s)."),
994*17Sdinak 		    pkcs11_strerror(rv));
995*17Sdinak 		return (rv);
996*17Sdinak 	}
997*17Sdinak 
998*17Sdinak 	/* Allocate memory for each attribute. */
999*17Sdinak 	for (i = 0; i < count; i++) {
1000*17Sdinak 		if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 ||
1001*17Sdinak 		    cert_attrs[i].ulValueLen == 0) {
1002*17Sdinak 			cryptodebug("cvt_cert2x509:  *** should not happen");
1003*17Sdinak 			cert_attrs[i].ulValueLen = 0;
1004*17Sdinak 			continue;
1005*17Sdinak 		}
1006*17Sdinak 		if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen))
1007*17Sdinak 		    == NULL) {
1008*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
1009*17Sdinak 			return (CKR_HOST_MEMORY);
1010*17Sdinak 		}
1011*17Sdinak 	}
1012*17Sdinak 
1013*17Sdinak 	/* Now really get the attributes. */
1014*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
1015*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
1016*17Sdinak 	    CKR_OK) {
1017*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1018*17Sdinak 		    "Unable to get certificate attributes (%s)."),
1019*17Sdinak 		    pkcs11_strerror(rv));
1020*17Sdinak 		return (rv);
1021*17Sdinak 	}
1022*17Sdinak 
1023*17Sdinak 	/*
1024*17Sdinak 	 * Fill in all the temp variables.  Subject and value are required.
1025*17Sdinak 	 * The rest are optional.
1026*17Sdinak 	 */
1027*17Sdinak 	i = 0;
1028*17Sdinak 	copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len);
1029*17Sdinak 	copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len);
1030*17Sdinak 
1031*17Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
1032*17Sdinak 	    cert_attrs[i].ulValueLen != 0)
1033*17Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &label, &label_len);
1034*17Sdinak 	i++;
1035*17Sdinak 
1036*17Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
1037*17Sdinak 	    cert_attrs[i].ulValueLen != 0)
1038*17Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &id, &id_len);
1039*17Sdinak 	i++;
1040*17Sdinak 
1041*17Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
1042*17Sdinak 	    cert_attrs[i].ulValueLen != 0)
1043*17Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len);
1044*17Sdinak 	i++;
1045*17Sdinak 
1046*17Sdinak 	if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
1047*17Sdinak 	    cert_attrs[i].ulValueLen != 0)
1048*17Sdinak 		copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len);
1049*17Sdinak 	i++;
1050*17Sdinak 
1051*17Sdinak 	/* Start the conversion to internal OpenSSL X509 structure. */
1052*17Sdinak 
1053*17Sdinak 	/* Subject name (required) */
1054*17Sdinak 	cryptodebug("calling d2i_X509_NAME for subject name");
1055*17Sdinak 	if ((ssl_subject = d2i_X509_NAME(NULL, &subject, subject_len)) ==
1056*17Sdinak 	    NULL) {
1057*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1058*17Sdinak 		    "Unable to convert certificate subject name."));
1059*17Sdinak 		return (CKR_GENERAL_ERROR);
1060*17Sdinak 	}
1061*17Sdinak 	cryptodebug("calling X509_set_subject_name");
1062*17Sdinak 	if (!X509_set_subject_name(cert, ssl_subject)) {
1063*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1064*17Sdinak 		    "Unable to pack certificate subject name entries."));
1065*17Sdinak 		return (CKR_GENERAL_ERROR);
1066*17Sdinak 	}
1067*17Sdinak 
1068*17Sdinak 	/* Label (optional) */
1069*17Sdinak 	cryptodebug("calling X509_alias_set1");
1070*17Sdinak 	if (!X509_alias_set1(cert, label, label_len))
1071*17Sdinak 		cryptodebug("error not caught");
1072*17Sdinak 
1073*17Sdinak 	/* Id (optional) */
1074*17Sdinak 	cryptodebug("calling X509_keyid_set1");
1075*17Sdinak 	if (!X509_keyid_set1(cert, id, id_len))
1076*17Sdinak 		cryptodebug("error not caught");
1077*17Sdinak 
1078*17Sdinak 	/* Issuer name (optional) */
1079*17Sdinak 	cryptodebug("calling d2i_X509_NAME for issuer name");
1080*17Sdinak 	if ((ssl_issuer = d2i_X509_NAME(NULL, &issuer, issuer_len)) == NULL) {
1081*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1082*17Sdinak 		    "Unable to convert certificate issuer name."));
1083*17Sdinak 		return (CKR_GENERAL_ERROR);
1084*17Sdinak 	}
1085*17Sdinak 	cryptodebug("calling X509_set_issuer_name");
1086*17Sdinak 	if (!X509_set_issuer_name(cert, ssl_issuer)) {
1087*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1088*17Sdinak 		    "Unable to pack certificate issuer name entries."));
1089*17Sdinak 		return (CKR_GENERAL_ERROR);
1090*17Sdinak 	}
1091*17Sdinak 
1092*17Sdinak 	/* Serial number (optional) */
1093*17Sdinak 	cryptodebug("calling c2i_ASN1_INTEGER for serial number");
1094*17Sdinak 	if ((ssl_serial = c2i_ASN1_INTEGER(NULL, &serial, serial_len)) ==
1095*17Sdinak 	    NULL) {
1096*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1097*17Sdinak 		    "Unable to convert certificate serial number."));
1098*17Sdinak 		return (CKR_GENERAL_ERROR);
1099*17Sdinak 	}
1100*17Sdinak 	cryptodebug("calling X509_set_serialNumber");
1101*17Sdinak 	if (!X509_set_serialNumber(cert, ssl_serial))
1102*17Sdinak 		cryptodebug("error not caught");
1103*17Sdinak 
1104*17Sdinak 	/*
1105*17Sdinak 	 * Value (required)
1106*17Sdinak 	 *
1107*17Sdinak 	 * The rest of this code takes the CKA_VALUE attribute, converts
1108*17Sdinak 	 * it into a temp OpenSSL X509 structure and picks out the rest
1109*17Sdinak 	 * of the fields we need to convert it back into the current X509
1110*17Sdinak 	 * structure that will get exported.  The reason we don't just
1111*17Sdinak 	 * start with CKA_VALUE is because while the object was in the
1112*17Sdinak 	 * softtoken, it is possible that some of its attributes changed.
1113*17Sdinak 	 * Those changes would not appear in CKA_VALUE and would be lost
1114*17Sdinak 	 * if we started with CKA_VALUE that was saved originally.
1115*17Sdinak 	 */
1116*17Sdinak 	cryptodebug("calling d2i_X509 for cert value");
1117*17Sdinak 	if ((temp_cert = d2i_X509(NULL, &value, value_len)) == NULL) {
1118*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1119*17Sdinak 		    "Unable to convert main certificate values."));
1120*17Sdinak 		return (CKR_GENERAL_ERROR);
1121*17Sdinak 	}
1122*17Sdinak 
1123*17Sdinak 	/* Transfer these values from temp_cert to cert. */
1124*17Sdinak 	cryptodebug("calling X509_set_version/X509_get_version");
1125*17Sdinak 	if (!X509_set_version(cert, X509_get_version(temp_cert)))
1126*17Sdinak 		cryptodebug("error not caught");
1127*17Sdinak 
1128*17Sdinak 	cryptodebug("calling X509_set_notBefore/X509_get_notBefore");
1129*17Sdinak 	if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert)))
1130*17Sdinak 		cryptodebug("error not caught");
1131*17Sdinak 
1132*17Sdinak 	cryptodebug("calling X509_set_notAfter/X509_get_notAfter");
1133*17Sdinak 	if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert)))
1134*17Sdinak 		cryptodebug("error not caught");
1135*17Sdinak 
1136*17Sdinak 	cryptodebug("calling X509_set_pubkey/X509_get_pubkey");
1137*17Sdinak 	if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert)))
1138*17Sdinak 		cryptodebug("error not caught");
1139*17Sdinak 
1140*17Sdinak 	/*
1141*17Sdinak 	 * These don't get transfered from temp_cert to cert.
1142*17Sdinak 	 * It -appears- that they may get regenerated as needed.
1143*17Sdinak 	 *
1144*17Sdinak 	 * cert->cert_info->signature = dup(temp_cert->cert_info->signature);
1145*17Sdinak 	 * cert->sig_alg = dup(temp_cert->sig_alg);
1146*17Sdinak 	 * cert->signature = dup(temp_cert->signature);
1147*17Sdinak 	 * cert->skid = dup(temp_cert->skid);
1148*17Sdinak 	 * cert->akid = dup(temp_cert->akid);
1149*17Sdinak 	 */
1150*17Sdinak 
1151*17Sdinak 	*c = cert;
1152*17Sdinak 	return (CKR_OK);
1153*17Sdinak }
1154*17Sdinak 
1155*17Sdinak static CK_RV
1156*17Sdinak convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
1157*17Sdinak 	CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len,
1158*17Sdinak 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
1159*17Sdinak {
1160*17Sdinak 	CK_RV		rv = CKR_OK;
1161*17Sdinak 	EVP_PKEY	*pk = NULL;
1162*17Sdinak 	X509		*c = NULL;
1163*17Sdinak 	X509		*one_ca = NULL;
1164*17Sdinak 	STACK_OF(X509)	*ch = NULL;
1165*17Sdinak 	int		i;
1166*17Sdinak 
1167*17Sdinak 	cryptodebug("inside convert_token_objs");
1168*17Sdinak 
1169*17Sdinak 	if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK)
1170*17Sdinak 		return (rv);
1171*17Sdinak 
1172*17Sdinak 	if (mate != ~0UL) {
1173*17Sdinak 		cryptodebug("converting cert corresponding to private key");
1174*17Sdinak 		if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK)
1175*17Sdinak 			return (rv);
1176*17Sdinak 	}
1177*17Sdinak 
1178*17Sdinak 	if (chain_len != 0) {
1179*17Sdinak 		cryptodebug("converting ca chain of %d certs corresponding "
1180*17Sdinak 		    "to private key", chain_len);
1181*17Sdinak 		ch = sk_X509_new_null();
1182*17Sdinak 		for (i = 0; i < chain_len; i++) {
1183*17Sdinak 			if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) !=
1184*17Sdinak 			    CKR_OK) {
1185*17Sdinak 				return (rv);
1186*17Sdinak 			}
1187*17Sdinak 			if (!sk_X509_push(ch, one_ca))
1188*17Sdinak 				cryptodebug("error not caught");
1189*17Sdinak 		}
1190*17Sdinak 	}
1191*17Sdinak 
1192*17Sdinak 	*priv_key = pk;
1193*17Sdinak 	*cert = (mate != ~0UL) ? c : NULL;
1194*17Sdinak 	*ca = (chain_len != 0) ? ch : NULL;
1195*17Sdinak 	return (CKR_OK);
1196*17Sdinak }
1197*17Sdinak 
1198*17Sdinak /*
1199*17Sdinak  * Export objects from token to PKCS#12 file.
1200*17Sdinak  */
1201*17Sdinak int
1202*17Sdinak pk_export(int argc, char *argv[])
1203*17Sdinak {
1204*17Sdinak 	char		*token_name = NULL;
1205*17Sdinak 	char		*manuf_id = NULL;
1206*17Sdinak 	char		*serial_no = NULL;
1207*17Sdinak 	char		full_name[FULL_NAME_LEN];
1208*17Sdinak 	char		*filename = NULL;
1209*17Sdinak 	CK_SLOT_ID	slot_id;
1210*17Sdinak 	CK_FLAGS	pin_state;
1211*17Sdinak 	CK_UTF8CHAR_PTR	pin = NULL;
1212*17Sdinak 	CK_ULONG	pinlen = 0;
1213*17Sdinak 	CK_UTF8CHAR_PTR	pk12pin = NULL;
1214*17Sdinak 	CK_ULONG	pk12pinlen = 0;
1215*17Sdinak 	CK_SESSION_HANDLE	sess;
1216*17Sdinak 	BIO		*fbio = NULL;
1217*17Sdinak 	EVP_PKEY	*priv_key = NULL;
1218*17Sdinak 	X509		*cert = NULL;
1219*17Sdinak 	STACK_OF(X509)	*ca = NULL;
1220*17Sdinak 	CK_RV		rv = CKR_OK;
1221*17Sdinak 	CK_OBJECT_HANDLE	*objs = NULL;
1222*17Sdinak 	CK_ULONG	num_objs = 0;
1223*17Sdinak 	CK_OBJECT_HANDLE	mate = ~0UL;
1224*17Sdinak 	CK_OBJECT_HANDLE	*chain = NULL;
1225*17Sdinak 	CK_ULONG	chain_len;
1226*17Sdinak 	CK_BYTE		*id = NULL;
1227*17Sdinak 	CK_ULONG	id_len = 0;
1228*17Sdinak 	int		i = 0;
1229*17Sdinak 	int		good_ones = 0, bad_ones = 0;	/* running totals */
1230*17Sdinak 
1231*17Sdinak 	cryptodebug("inside pk_export");
1232*17Sdinak 
1233*17Sdinak 	/* Get rid of subcommand work "export". */
1234*17Sdinak 	argc--;
1235*17Sdinak 	argv++;
1236*17Sdinak 
1237*17Sdinak 	/* One additional arg required:  filename. */
1238*17Sdinak 	if (argc != 1)
1239*17Sdinak 		return (PK_ERR_USAGE);
1240*17Sdinak 
1241*17Sdinak 	filename = argv[0];
1242*17Sdinak 	/* Done parsing command line options. */
1243*17Sdinak 
1244*17Sdinak 	/* Check if the file exists and might be overwritten. */
1245*17Sdinak 	if (access(filename, F_OK) == 0) {
1246*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, "
1247*17Sdinak 		    "will be overwritten."), filename);
1248*17Sdinak 		if (yesno(gettext("Continue with export? "),
1249*17Sdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
1250*17Sdinak 			return (0);
1251*17Sdinak 		}
1252*17Sdinak 	}
1253*17Sdinak 
1254*17Sdinak 	/* Export operation only supported on softtoken. */
1255*17Sdinak 	if (token_name == NULL)
1256*17Sdinak 		token_name = SOFT_TOKEN_LABEL;
1257*17Sdinak 	if (manuf_id == NULL)
1258*17Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
1259*17Sdinak 	if (serial_no == NULL)
1260*17Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
1261*17Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
1262*17Sdinak 
1263*17Sdinak 	/* Find the slot with token. */
1264*17Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
1265*17Sdinak 	    &pin_state)) != CKR_OK) {
1266*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1267*17Sdinak 		    "Unable to find token %s (%s)."), full_name,
1268*17Sdinak 		    pkcs11_strerror(rv));
1269*17Sdinak 		return (PK_ERR_PK11);
1270*17Sdinak 	}
1271*17Sdinak 
1272*17Sdinak 	/* Get the user's PIN. */
1273*17Sdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
1274*17Sdinak 	    &pinlen)) != CKR_OK) {
1275*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1276*17Sdinak 		    "Unable to get token passphrase (%s)."),
1277*17Sdinak 		    pkcs11_strerror(rv));
1278*17Sdinak 		quick_finish(NULL);
1279*17Sdinak 		return (PK_ERR_PK11);
1280*17Sdinak 	}
1281*17Sdinak 
1282*17Sdinak 	/* Assume user must be logged in R/W to export objects from token. */
1283*17Sdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
1284*17Sdinak 	    CKR_OK) {
1285*17Sdinak 		cryptoerror(LOG_STDERR,
1286*17Sdinak 		    gettext("Unable to log into token (%s)."),
1287*17Sdinak 		    pkcs11_strerror(rv));
1288*17Sdinak 		quick_finish(sess);
1289*17Sdinak 		return (PK_ERR_PK11);
1290*17Sdinak 	}
1291*17Sdinak 
1292*17Sdinak 	/* Collect all private keys first. */
1293*17Sdinak 	if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL,
1294*17Sdinak 	    &objs, &num_objs)) != CKR_OK) {
1295*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
1296*17Sdinak 		    "Unable to retrieve private key token objects (%s)."),
1297*17Sdinak 		    pkcs11_strerror(rv));
1298*17Sdinak 		quick_finish(sess);
1299*17Sdinak 		return (PK_ERR_PK11);
1300*17Sdinak 	}
1301*17Sdinak 
1302*17Sdinak 	/* Nothing to do? */
1303*17Sdinak 	if (num_objs == 0) {
1304*17Sdinak 		cryptoerror(LOG_STDERR, gettext("No objects found."));
1305*17Sdinak 		quick_finish(sess);
1306*17Sdinak 		return (0);
1307*17Sdinak 	}
1308*17Sdinak 
1309*17Sdinak 	/* Setup OpenSSL context. */
1310*17Sdinak 	PKTOOL_setup_openssl();
1311*17Sdinak 
1312*17Sdinak 	/* Create PKCS#12 file. */
1313*17Sdinak 	if ((create_pkcs12(filename, &fbio)) < 0) {
1314*17Sdinak 		cryptoerror(LOG_STDERR, gettext("No export file created."));
1315*17Sdinak 		quick_finish(sess);
1316*17Sdinak 		return (PK_ERR_SYSTEM);
1317*17Sdinak 	}
1318*17Sdinak 
1319*17Sdinak 	/* Get the PIN for the PKCS#12 export file. */
1320*17Sdinak 	if ((rv = get_pin(gettext("Create export file passphrase:"), gettext(
1321*17Sdinak 	    "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) !=
1322*17Sdinak 	    CKR_OK) {
1323*17Sdinak 		cryptoerror(LOG_STDERR,
1324*17Sdinak 		    gettext("Unable to get export file passphrase (%s)."),
1325*17Sdinak 		    pkcs11_strerror(rv));
1326*17Sdinak 		close_pkcs12(fbio);
1327*17Sdinak 		quick_finish(sess);
1328*17Sdinak 		return (PK_ERR_PK11);
1329*17Sdinak 	}
1330*17Sdinak 
1331*17Sdinak 	for (i = 0; i < num_objs; i++) {
1332*17Sdinak 		/* Get a private key and its certificate and CA chain. */
1333*17Sdinak 		if ((rv = get_token_objs(sess, objs[i], &mate, &chain,
1334*17Sdinak 		    &chain_len, &id, &id_len)) != CKR_OK) {
1335*17Sdinak 			/*
1336*17Sdinak 			 * Note this "rv" is either CKR_OK or !CKR_OK.  The
1337*17Sdinak 			 * real error codes/messages are handled inside
1338*17Sdinak 			 * read_token_objs().
1339*17Sdinak 			 */
1340*17Sdinak 			cryptoerror(LOG_STDERR,
1341*17Sdinak 			    gettext("Unable to get token objects."));
1342*17Sdinak 			free(id);
1343*17Sdinak 			close_pkcs12(fbio);
1344*17Sdinak 			quick_finish(sess);
1345*17Sdinak 			return (PK_ERR_PK11);
1346*17Sdinak 		}
1347*17Sdinak 
1348*17Sdinak 		/* Convert to OpenSSL equivalents. */
1349*17Sdinak 		if ((rv = convert_token_objs(sess, objs[i], mate, chain,
1350*17Sdinak 		    chain_len, &priv_key, &cert, &ca)) != CKR_OK) {
1351*17Sdinak 			/*
1352*17Sdinak 			 * Note this "rv" is either CKR_OK or !CKR_OK.  The
1353*17Sdinak 			 * real error codes/messages are handled inside
1354*17Sdinak 			 * read_token_objs().
1355*17Sdinak 			 */
1356*17Sdinak 			cryptoerror(LOG_STDERR,
1357*17Sdinak 			    gettext("Unable to convert token objects."));
1358*17Sdinak 			free(id);
1359*17Sdinak 			close_pkcs12(fbio);
1360*17Sdinak 			quick_finish(sess);
1361*17Sdinak 			return (PK_ERR_PK11);
1362*17Sdinak 		}
1363*17Sdinak 
1364*17Sdinak 		/*
1365*17Sdinak 		 * When exporting of cert chains is implemented, these
1366*17Sdinak 		 * messages should be updated accordingly.
1367*17Sdinak 		 */
1368*17Sdinak 		if (mate == ~0UL)
1369*17Sdinak 			(void) fprintf(stdout, gettext(
1370*17Sdinak 			    "Writing object #%d...\n"), i+1);
1371*17Sdinak 		else
1372*17Sdinak 			(void) fprintf(stdout, gettext("Writing object #%d "
1373*17Sdinak 			    "and its certificate...\n"), i+1);
1374*17Sdinak 
1375*17Sdinak 		/* Write object and its certs to the PKCS#12 export file. */
1376*17Sdinak 		if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len,
1377*17Sdinak 		    priv_key, cert, ca, &good_ones, &bad_ones) < 0) {
1378*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
1379*17Sdinak 			    "Unable to write object #%d to export file."), i+1);
1380*17Sdinak 			sk_X509_pop_free(ca, X509_free);
1381*17Sdinak 			free(id);
1382*17Sdinak 			close_pkcs12(fbio);
1383*17Sdinak 			quick_finish(sess);
1384*17Sdinak 			return (PK_ERR_OPENSSL);
1385*17Sdinak 		}
1386*17Sdinak 
1387*17Sdinak 		/* Destroy key id and CA cert chain, done with them. */
1388*17Sdinak 		free(id);
1389*17Sdinak 		id = NULL;
1390*17Sdinak 		sk_X509_pop_free(ca, X509_free);
1391*17Sdinak 		ca = NULL;
1392*17Sdinak 	}
1393*17Sdinak 
1394*17Sdinak 	(void) fprintf(stdout, gettext(
1395*17Sdinak 	    "%d token objects exported, %d errors occurred.\n"),
1396*17Sdinak 	    good_ones, bad_ones);
1397*17Sdinak 
1398*17Sdinak 	/* Close PKCS#12 file. */
1399*17Sdinak 	close_pkcs12(fbio);
1400*17Sdinak 
1401*17Sdinak 	/* Clean up. */
1402*17Sdinak 	quick_finish(sess);
1403*17Sdinak 	return (0);
1404*17Sdinak }
1405